Client compiling Weapon problem. Created 1 year ago2023-02-09 02:36:09 UTC by RoJAn RoJAn

Created 1 year ago2023-02-09 02:36:09 UTC by RoJAn RoJAn

Posted 1 year ago2023-02-09 02:36:09 UTC Post #347313
Hi, i recently created an account here just to ask for help about creating a Half-Life Weapon.
You see, im working on a nail gun like in TFC and because im really amateur at this, i get this error when compiling the cl_dll.

`1>hl_weapons.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall CBasePlayer::Touch(class CBaseEntity *)" (?Touch@CBasePlayer@@UAEXPAVCBaseEntity@@@Z)
1>Debug\hl_cdll\client.dll : fatal error LNK1120: 1 unresolved externals`

Im most secure that is something simple, but i can't find anything related to it, so i'm completely lost.
Can someone know the reason?
Posted 1 year ago2023-02-09 15:49:56 UTC Post #347318
Without the full code of the weapon you're trying to program, this is complicated to tell exactly what's wrong.

My guess is that the projectile (in this case, the nail) is both part of the client and the server. The projectile should only be on the server (between an #ifndef CLIENT_DLL and #endif block), look at the RPG's rocket, snark as a monster or placed tripmine for an example.
Posted 1 year ago2023-02-09 22:07:37 UTC Post #347322
Well you see, i tried to replicate the quake nail of Deathmatch Classic to create this weapon... So you will see enough copy paste of the code triying to replicate it on the HL base code. Some of the functions for the nail projectiles where already on the Client files, so i dont know how much this causes the main problem. I don't even think this weapon shoots even, i really need someone to diagnose this terribleness.

nailgun.cpp

#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )

#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "decals.h"
#include "gamerules.h"

enum ngun_e {
NGUN_IDLE1 = 0,
NGUN_FIDGETSWAY,
NGUN_FIDGETSHAKE,
NGUN_DOWN,
NGUN_UP,
NGUN_SHOOT
};

enum firemode_e
{
FIREMODE_TRACK = 0,
FIREMODE_FAST
};

#ifndef CLIENT_DLL

LINK_ENTITY_TO_CLASS(quake_nail, CQuakeNail);

//=========================================================
CQuakeNail* CQuakeNail::CreateNail(Vector vecOrigin, Vector vecAngles, CBaseEntity* pOwner)
{
CQuakeNail* pNail = GetClassPtr((CQuakeNail*)NULL);

UTIL_SetOrigin(pNail->pev, vecOrigin);

pNail->pev->velocity = vecAngles * 1000;
pNail->pev->angles = UTIL_VecToAngles(vecAngles);
pNail->pev->owner = pOwner->edict();
pNail->Spawn();
pNail->pev->classname = MAKE_STRING("spike");

// don't send to clients.
pNail->pev->effects |= EF_NODRAW;

return pNail;
}

CQuakeNail* CQuakeNail::CreateSuperNail(Vector vecOrigin, Vector vecAngles, CBaseEntity* pOwner)
{
CQuakeNail* pNail = CreateNail(vecOrigin, vecAngles, pOwner);
pNail->pev->classname = MAKE_STRING("superspike");

// Super nails simply do more damage
pNail->pev->dmg = 18;
return pNail;
}

void CQuakeNail::Precache(void)
{
PRECACHE_MODEL("models/nail.mdl");
}

//=========================================================
void CQuakeNail::Spawn(void)
{
Precache();

// Setup
pev->movetype = MOVETYPE_FLYMISSILE;
pev->solid = SOLID_BBOX;

// Safety removal
pev->nextthink = gpGlobals->time + 6;
SetThink(&CQuakeNail::SUB_Remove);

// Touch
SetTouch(&CQuakeNail::NailTouch);

// Model
SET_MODEL(ENT(pev), "models/nail.mdl");
UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0));
UTIL_SetOrigin(pev, pev->origin);

// Damage
pev->dmg = 9;
}

//=========================================================
void CQuakeNail::NailTouch(CBaseEntity* pOther)
{
if (pOther->pev->solid == SOLID_TRIGGER)
return;

// Remove if we've hit skybrush
if (UTIL_PointContents(pev->origin) == CONTENT_SKY)
{
UTIL_Remove(this);
return;
}

// Hit something that bleeds
if (pOther->pev->takedamage)
{
CBaseEntity* pOwner = CBaseEntity::Instance(pev->owner);

if (g_pGameRules->PlayerRelationship(pOther, pOwner) != GR_TEAMMATE)
SpawnBlood(pev->origin, pOther->BloodColor(), pev->dmg);

pOther->TakeDamage(pev, pOwner->pev, pev->dmg, DMG_GENERIC);
}
else
{
if (pOther->pev->solid == SOLID_BSP || pOther->pev->movetype == MOVETYPE_PUSHSTEP)
{
TraceResult tr;
tr.vecEndPos = pev->origin;
tr.pHit = pOther->edict();

//Arent we doing this client side?
//UTIL_GunshotDecalTrace( &tr, DECAL_GUNSHOT1 + RANDOM_LONG( 0, 4 ) );
}
}

UTIL_Remove(this);
}
#endif

LINK_ENTITY_TO_CLASS(weapon_nailgun, CNailGun);

void CNailGun::Spawn()
{
Precache();
m_iId = WEAPON_NAILGUN;
SET_MODEL(ENT(pev), "models/w_hgun.mdl");

m_iDefaultAmmo = NAILGUN_DEFAULT_GIVE;
m_iFirePhase = 0;

pev->solid = SOLID_TRIGGER;

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

void CNailGun::Precache(void)
{
PRECACHE_MODEL("models/v_tfc_nailgun.mdl");
PRECACHE_MODEL("models/w_hgun.mdl");
PRECACHE_MODEL("models/p_nailgun.mdl");
PRECACHE_SOUND("weapons/airgun_1.wav");

m_usNailFire = PRECACHE_EVENT(1, "events/wpn/Tf_nail.sc");

UTIL_PrecacheOther("nail");
}

int CNailGun::AddToPlayer(CBasePlayer* pPlayer)
{
if (CBasePlayerWeapon::AddToPlayer(pPlayer))
{

#ifndef CLIENT_DLL
if (g_pGameRules->IsMultiplayer())
{
// in multiplayer, all hivehands come full.
pPlayer->m_rgAmmo[PrimaryAmmoIndex()] = NAILGUN_MAX_CARRY;
}
#endif

MESSAGE_BEGIN(MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev);
WRITE_BYTE(m_iId);
MESSAGE_END();
return TRUE;
}
return FALSE;
}

int CNailGun::GetItemInfo(ItemInfo* p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "9mm";
p->iMaxAmmo1 = NAILGUN_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = WEAPON_NOCLIP;
p->iSlot = 1;
p->iPosition = 3;
p->iId = m_iId = WEAPON_NAILGUN;
p->iFlags = 0;
p->iWeight = NAILGUN_WEIGHT;

return 1;
}

BOOL CNailGun::Deploy()
{
return DefaultDeploy("models/v_tfc_nailgun.mdl", "models/p_nailgun.mdl", NGUN_UP, "mp5",1);
}

void CNailGun::PrimaryAttack()
{
Reload();

if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
{
PlayEmptySound();
return;
}

m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH;
PLAYBACK_EVENT_FULL(1, ENT(m_pPlayer->pev), m_usNailFire, 0, (float*)&g_vecZero, (float*)&g_vecZero, 0, 0, 0, 0, 0, 0);
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
m_flTimeWeaponIdle = 10;
m_flNextPrimaryAttack = 0.1;

}

void CNailGun::WeaponIdle(void)
{
Reload();

if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
return;

int iAnim;
float flRand = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 0, 1);
if (flRand <= 0.75)
{
iAnim = NGUN_IDLE1;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 30.0 / 16 * (2);
}
else if (flRand <= 0.875)
{
iAnim = NGUN_FIDGETSWAY;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 40.0 / 16.0;
}
else
{
iAnim = NGUN_FIDGETSHAKE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 35.0 / 16.0;
}
SendWeaponAnim(iAnim);
}

#endif

weapons.h

//constant items
/Blah blah blah code/
#define WEAPON_NAILGUN 16

// weapon weight factors (for auto-switching) (-1 = noswitch)
/Blah blah blah code/
#define NAILGUN_WEIGHT 10

// weapon clip/carry ammo capacities
/Blah blah blah code/
#define NAILGUN_MAX_CARRY 100

// Max clip section
/Blah blah blah code/
#define NAILGUN_MAX_CLIP WEAPON_NOCLIP

// the default amount of ammo that comes with each gun when it spawns
/Blah blah blah code/
#define NAILGUN_DEFAULT_GIVE 50

(Didnt write the ammo given to a player by an ammo item)

/Blah blah blah class code/

class CNailGun : public CBasePlayerWeapon
{
public:
void Spawn(void);
void Precache(void);
int iItemSlot(void) { return 2; }
int GetItemInfo(ItemInfo* p);
int AddToPlayer(CBasePlayer* pPlayer);

void PrimaryAttack(void);
BOOL Deploy(void);
void WeaponIdle(void);

int m_iFirePhase;// don't save me.

virtual BOOL UseDecrement(void)
{
#if defined( CLIENT_WEAPONS )
return TRUE;
#else
return FALSE;
#endif
}
private:
unsigned short m_usNailFire;
};

class CQuakeNail : public CBaseEntity
{
public:
void Spawn(void);
void Precache(void);
static CQuakeNail* CreateNail(Vector vecOrigin, Vector vecAngles, CBaseEntity* pOwner);
static CQuakeNail* CreateSuperNail(Vector vecOrigin, Vector vecAngles, CBaseEntity* pOwner);
void EXPORT NailTouch(CBaseEntity* pOther);
};
Posted 1 year ago2023-02-09 22:08:32 UTC Post #347323
theres more if you need:

hl_weapons.cpp

// HLDM Weapon placeholder entities.
CNailGun g_Nailgun;
/Blah blah blah code/
CQuakeNail* CQuakeNail::CreateSuperNail(Vector vecOrigin, Vector vecAngles, CBaseEntity* pOwner)
{
return NULL;
}

CQuakeNail* CQuakeNail::CreateNail(Vector vecOrigin, Vector vecAngles, CBaseEntity* pOwner)
{
return NULL;
}
/////////////
Blah blah blah
/////////////
void HUD_InitClientWeapons( void )
/Blah blah blah code/
HUD_PrepEntity( &g_Nailgun , &player );

// FIXME, make this a method in each weapon? where you pass in an entity_state_t *?
switch ( from->client.m_iId )
{
case WEAPON_CROWBAR:
pWeapon = &g_Crowbar;
break;

/Blah blah blah code/

case WEAPON_NAILGUN:
pWeapon = &g_Nailgun;
break;
}

ev_hldm.cpp

extern C
{
//HLDM
/blah blah blah code/
void EV_NailgunFire(struct event_args_s* args);

void EV_TrainPitchAdjust( struct event_args_s *args );
}

/blah blah code/

void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType )
{
/blah blah code/
if ( pe && pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP)
{
switch( iBulletType )
{
case BULLET_PLAYER_9MM:
case BULLET_MONSTER_9MM:
case BULLET_PLAYER_MP5:
case BULLET_MONSTER_MP5:
case BULLET_PLAYER_BUCKSHOT:
case BULLET_PLAYER_357:
default:
// smoke and decal
EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ) );
break;
}
}
}

/blah blah blah, too much code later/

//======================
// SQUEAK END
//======================
//======================
// NAIL START
//======================
enum ngun_e {
NGUN_IDLE1 = 0,
NGUN_FIDGETSWAY,
NGUN_FIDGETSHAKE,
NGUN_DOWN,
NGUN_UP,
NGUN_SHOOT
};

void EV_NailgunFire(event_args_t* args)
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
vec3_t up, right, forward;

vec3_t ShellVelocity;
vec3_t ShellOrigin;
int shell;
vec3_t vecSrc, vecAiming;

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/nail.mdl");

if (EV_IsLocal(idx))
gEngfuncs.pEventAPI->EV_WeaponAnimation(NGUN_SHOOT, 2);
EV_GetGunPosition(args, ShellOrigin, origin);
VectorMA(ShellOrigin, -4.0, up, ShellOrigin);
VectorMA(ShellOrigin, 2.0, right, ShellOrigin);
gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_WEAPON, "weapons/airgun_1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), 0.8, 0, gEngfuncs.pfnRandomLong(0, 31) + 93);
VectorScale(forward, 1000.0, velocity);
gEngfuncs.pEfxAPI->R_Projectile(ShellOrigin, velocity, shell, 6, idx, EV_Quake_NailTouch);
if (EV_IsLocal(idx))
V_PunchAxis(0, -1.0);
}
//======================
// NAIL END
//======================

void EV_Quake_NailTouch(struct tempent_s* ent, pmtrace_t* ptr)
{
physent_t* pe;
char name;

pe = gEngfuncs.pEventAPI->EV_GetPhysent(ptr->ent);
if (pe && (pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP))
{
sprintf(&name, "{shot%i", gEngfuncs.pfnRandomLong(0, 4) + 1);
if (name)
{
if (ptr->fraction != 1.0)
EV_HLDM_GunshotDecalTrace(ptr, &name);
}
}
}
....
EV_NailgunFire is already declared on hl_events.cpp
You must be logged in to post a response.