Looks like I have a lot to learn in C++ besides the main syntax 😅
Anyway, I finally have nothing to ask. Thanks for your patience when answering my dumb questions :3
items.cpp
), and it solved the problem, so the reason is one of these includes. How...?#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "UserMessages.h"
#include "cstring"
class CTargetChangeHudColor : public CBaseEntity
{
public:
// make these variables private, probably?
// nothing should change them directly
int m_iRed;
int m_iGreen;
int m_iBlue;
void Use(CBaseEntity* pActivator, CBaseEntity* pOther, USE_TYPE useType, float value) override;
bool KeyValue(KeyValueData* pkvd) override;
};
LINK_ENTITY_TO_CLASS(target_change_hud_color, CTargetChangeHudColor);
bool CTargetChangeHudColor::KeyValue(KeyValueData* pkvd)
{
if (FStrEq(pkvd->szKeyName, "red"))
{
m_iRed = atof(pkvd->szValue);
return true;
}
else if (FStrEq(pkvd->szKeyName, "green"))
{
m_iGreen = atof(pkvd->szValue);
return true;
}
else if (FStrEq(pkvd->szValue, "blue"))
{
m_iBlue = atof(pkvd->szValue);
return true;
}
return CBaseEntity::KeyValue(pkvd);
}
void CTargetChangeHudColor::Use(CBaseEntity* pActivator, CBaseEntity* pOther, USE_TYPE useType, float value)
{
CBasePlayer* player;
// errors here
if (pActivator->IsPlayer())
player = static_cast<CBasePlayer*>(pActivator);
else
player = static_cast<CBasePlayer*>(pOther);
// MESSAGE_BEGIN(MSG_ONE, gmsgHudColor, NULL, player->pev);
MESSAGE_BEGIN(MSG_ALL, gmsgHudColor);
WRITE_SHORT(m_iRed);
WRITE_SHORT(m_iGreen);
WRITE_SHORT(m_iBlue);
MESSAGE_END();
}
I don't know which entity is calling player (who pressed the button), so I checked both of them. This article says something about pCaller
, however, I don't see such variable in the method signature.@Admer456 said:Nope, it's exactly
It's probably anentvars_t*
CBaseEntity*
; at least, the method signature says so. All attempts were in the CBaseEntity::Use()
method override. Maybe, some Unified SDK bug? I double-checked everything to be correct. Otherwise, I wouldn't be asking - I prefer to solve by myself mostly, without asking someone to do this instead of me, unless I don't have another option and Google can't help me.@Admer456 said:Oh, it explains.
They knew about good principles, they just didn't really have the time to apply em. Between 1996 and 1998, the game spec changed so rapidly and so much, nobody could really keep up. Game code is very patchy, very volatile, and rapidly evolves. It's simply like that by nature.
@Admer456 said:Sorry for asking without clarification.
It is possible you were getting errors because you were casting to CBasePlayer and not CBasePlayer*. This is just C++'s value and reference semantics. In C#, a value type is a struct. In C++, a value type is anything that isn't a pointer. So you were trying to, essentially, convert a reference type into a value type there. Possibly, I'm just guessing.
if (pOther->IsPlayer())
player = static_cast<CBasePlayer*>(pOther); // invalid type conversion
Have no idea why it gives an error. I read that this may also occur when inheritance is private, but it's public in SDK code.player = dynamic_cast<CBasePlayer*>(pOther); // the type in a dynamic_cast must be a pointer or reference to a complete class type, or void *
I believe I've already indicated that I need a pointer by using an asterisk. At least, when I used dynamic_cast
multiple times trying to cast from CBaseEntity
to CBasePlayer
through the inheritance chain, it worked fine with all classes but CBasePlayer
.@Admer456 said:Is just like the one I used and caused the same error (if ( pEntity->IsPlayer() ) { CBasePlayer* player = static_cast<CBasePlayer*>( pEntity ); ... }
invalid type conversion
). The only difference is that I changed pEntity
to pOther
(since I used your snippet in the entity code), however, it does not look like the reason.CBasePlayer
from CBaseEntity
. static_cast
and dynamic_cast
, but they failed with different errors. I also tried to cast step-by-step through the inheritance chain (CBaseEntity -> CBaseDelay -> CBaseAnimating -> CBaseToggle -> CBaseMonster -> CBasePlayer
, if I'm not mistaken), and it still gives an error when trying to cast CBasePlayer
from CBaseMonster
. I (again) have no idea what causes these errors, so I am asking here.Tried to create a message with a bogus message type ( 0 )
in my case popped up because of a message name longer than 12 characters (I somehow skipped it in tutorial 😅).
@Admer456 said:Yeah, after a few days working with SDK, I'm starting to think that guys from Valve didn't know about any good coding practices or principles back in 1998. Otherwise, they could at least use folders to group files and make working with code a little less hell. Or, maybe, it wasn't possible in C++ back then... I don't know for sure, so I won't judge.
And yes, gHUD is the HUD singleton. It represents the clientside as a whole, almost a bit of a god object I'm afraid..
HUDManager
with static fields defining the RGB values, as well as a static method to change these values. I modified the UnpackRGB()
method to use the values from this class, and so far, it has worked with the default values (though I haven’t yet tried to use this method at runtime).HUDManager
is on the client side. So now I need a way to call a client-side method from the server.const.h
(from hl_cdll
) seem to help.UserMessages.cpp
in hldll
, which seems to use the REG_USER_MSG
method. This is a macro for g_engfuncs.pfnRegUserMsg
, which I presume, based on the file name and the comment above enginefuncs_s
, is an interface to an engine function of the same name. Since the engine’s code is not open-source, I can’t dig deeper to verify if this is the function I need. That’s why I’m asking for help.HUDManager
at runtime (which I haven’t yet tested), I’ll need to manually redraw the HUD to apply the new colors. My second question is: how can I do this? I found the gHUD
variable in cdll_int.h
, which I assume is the main HUD variable on the client side? The CHud
class (to which gHUD
belongs) has a Redraw
method with two arguments: flTime
and intermission
. What exactly does flTime
refer to (specifically the m_flTime
variable, which is assigned in the Redraw
method)? The comment says it's "the current client time," but the current time in what context and in what format? m_flTime
is used in so many places that I can’t quite grasp its meaning.