class reference crashing game

Grab your favourite IDE and tinker with the innards of game engines

class reference crashing game

Postby Mapster on Thu Mar 01, 2012 4:11 am

Hello Interlopers!
I have been trying to code a new key system for hl2 and have come across an error which i am assuming is due to variables not being initialized before being used, but not sure why its not working!

Whenever u try to reference CItemKeyBase anywhere else outside item_keys.cpp and item_keys.h, the game crashes.

Code: Select all
#ifndef ITEM_KEYS_H
#define ITEM_KEYS_H
#pragma once

#include "cbase.h"
#include "items.h"

// Max different coloured keys
#define SF_MAX_KEYS         6
#define SF_KEY_BLACK      131072
#define SF_KEY_BLUE         262144
#define SF_KEY_GREEN      524288
#define SF_KEY_RED         1048576
#define SF_KEY_WHITE      2097152
#define SF_KEY_YELLOW      4194304

class CItemKeyBase : public CItem
{
   public:
      DECLARE_CLASS( CItemKeyBase, CItem );
      DECLARE_DATADESC();

      CItemKeyBase::CItemKeyBase()
      {
         iKeyLists[1]=((int)SF_KEY_BLACK);
         iKeyLists[2]=((int)SF_KEY_BLUE);
         iKeyLists[3]=((int)SF_KEY_GREEN);
         iKeyLists[4]=((int)SF_KEY_RED);
         iKeyLists[5]=((int)SF_KEY_WHITE);
         iKeyLists[6]=((int)SF_KEY_YELLOW);
      };

      void Spawn( void );
      void Precache( void );
      bool MyTouch( CBasePlayer *pPlayer );
      bool bGivenKey(CBasePlayer *pPlayer, int iKey);

      virtual int GetKey(int key) { return iKeyLists[key]; };
      virtual int GetMaxKeys() { return iMaxKeys; };

   private:
      int iKeyLists[SF_MAX_KEYS];
      static int const iMaxKeys = (int)SF_MAX_KEYS;
      const char *m_smodel;
};

#endif


Not sure why this is happening but i have also tried using this as an array initializer but that doesn't seem to like it at all:
Code: Select all
static const int iKeyLists[] = { (int)SF_KEY_BLACK,(int)SF_KEY_BLUE,(int)SF_KEY_GREEN,(int)SF_KEY_RED,(int)SF_KEY_WHITE,(int)SF_KEY_YELLOW };


Any help would be greatly appreciated :)
Image
User avatar
Mapster
Member
Member
 
Joined: Thu Mar 01, 2012 4:07 am

Re: class reference crashing game

Postby zombie@computer on Thu Mar 01, 2012 9:30 am

arrays in c++ are zero-based. iKeyLists[6] is past the arrays' size (=6)

Why put those in a static array anyway? Using bitwise operators to get the value by index is probably faster than to actually look up the values in an array.

example

Code: Select all
int keyvalue = (1 << (16+index));
When you are up to your neck in shit, keep your head up high
zombie@computer
Forum Goer Elite™
Forum Goer Elite™
 
Joined: Fri Dec 31, 2004 5:58 pm
Location: Lent, Netherlands

Re: class reference crashing game

Postby Mapster on Fri Mar 02, 2012 6:50 am

Sorry im not too familiar with Bitwise Operators, i had a rough look over how to use them but it looked rather confusing, but i understand that they are used as a single boolean byte code where as int iKeyLists is used to store full length integers from the spawnflags.
Image
User avatar
Mapster
Member
Member
 
Joined: Thu Mar 01, 2012 4:07 am

Re: class reference crashing game

Postby zombie@computer on Fri Mar 02, 2012 2:06 pm

Mapster wrote:Sorry im not too familiar with Bitwise Operators, i had a rough look over how to use them but it looked rather confusing, but i understand that they are used as a single boolean byte code where as int iKeyLists is used to store full length integers from the spawnflags.

bitwise operators means computing with binary numbers.

eg.
Code: Select all
00100000 << 2 = 10000000 (shift bits 2 to the right)
00100000 >> 2 = 00001000 (shift bits 2 to the left)

01100000 |
10000000 =
11100000 (bitwise OR)

01101000 &
01000000 =
01000000 (bitwise AND)

bitwise operators are VERY fast (even faster than ordinary + and -)

if your array is only to contain 2^x numbers, its probably easier/faster to just bitwise operators to calculate the number than to actually store the numbers in an array.
When you are up to your neck in shit, keep your head up high
zombie@computer
Forum Goer Elite™
Forum Goer Elite™
 
Joined: Fri Dec 31, 2004 5:58 pm
Location: Lent, Netherlands

Re: class reference crashing game

Postby Mapster on Sun Mar 04, 2012 5:41 am

Alright i exchanged the array with the bitwise operators, must say its rather interesting now that i understand how it works, it all compiles fine but still crashes hammer whenever CItemKeyBase is referenced.

Code: Select all
#ifndef ITEM_KEYS_H
#define ITEM_KEYS_H
#pragma once

#include "cbase.h"
#include "items.h"

// Max different coloured keys
#define SF_MAX_KEYS         6
#define SF_KEY_BLACK      131072
#define SF_KEY_BLUE         262144
#define SF_KEY_GREEN      524288
#define SF_KEY_RED         1048576
#define SF_KEY_WHITE      2097152
#define SF_KEY_YELLOW      4194304

class CItemKeyBase : public CItem
{
   public:
      DECLARE_CLASS( CItemKeyBase, CItem );
      DECLARE_DATADESC();

      void Spawn( void );
      void Precache( void );
      bool MyTouch( CBasePlayer *pPlayer );
      bool bGivenKey(CBasePlayer *pPlayer, int iKey);

      virtual int GetKey(int key);
      virtual int GetMaxKeys() { return iMaxKeys; };

   private:
      static int const keyvalue = 00111111;
      static int const iMaxKeys = (int)SF_MAX_KEYS;

   protected:
      const char *m_smodel;
};

#endif


Code: Select all
int CItemKeyBase::GetKey(int key)
{
   int iTemp = ( 00000001 << (key-1));
   if ( iTemp & 00000001 ) return SF_KEY_BLACK;
   if ( iTemp & 00000010 ) return SF_KEY_BLUE;
   if ( iTemp & 00000100 ) return SF_KEY_GREEN;
   if ( iTemp & 00001000 ) return SF_KEY_RED;
   if ( iTemp & 00010000 ) return SF_KEY_WHITE;
   if ( iTemp & 00100000 ) return SF_KEY_YELLOW;

};
Image
User avatar
Mapster
Member
Member
 
Joined: Thu Mar 01, 2012 4:07 am

Re: class reference crashing game

Postby zombie@computer on Sun Mar 04, 2012 10:02 am

you cant just write 1's and 0's in code :) youll have to convert to hexadecimal or decimal and write that down.
Do you have win 7? Open the calculator and enter 'programmer' mode. It can do binary operators and convert hexadecimal to decimal to binary in a keypress...

plus, you dont really seem to understand what is EASY about this method.

First, declare your keys using an enumeration

(im sorry this may not be 100% valid c++, havent used it in a while)

Code: Select all
enum SF_KEYS
{
       SF_KEY_BLACK =  (1<<17),
       SF_KEY_BLUE =    (1<<18),
       SF_KEY_GREEN = (1<<19),
       SF_KEY_RED =     (1<<20),
       SF_KEY_WHITE = (1<<21),
       SF_KEY_YELLOW = (1<<22),
}; //note: do dot exceed 1<<30 as that will overflow the signed integer datatype

//then, to find out if someone has a certain key, you can do this for instance

int theKeysIveGot = 0;
//the user picked up a certain key
void AddKey(SF_KEYS key)
{
    theKeysIveGot |= key;
}
//does the user have this key?
bool HasKey(SF_KEYS key)
{
    return theKeysIveGot & key;//becomes 0 if the key isnt added or any other value if it is. in c++, 0=false, anything else=true
}
//remove a key from the user
void RemoveKey(SF_KEYS key)
{
    theKeysIveGot &= ~key;
    //note: the ~ create the inverse of a binary number: 11110111 becomes 00001000, etc
}

i dont see anything else that could cause your game to crash though. In fact, i doubt even this is the cause of the crash. Can you post some more code?

EDIT: wait, it crashes hammer? What do you mean?
When you are up to your neck in shit, keep your head up high
zombie@computer
Forum Goer Elite™
Forum Goer Elite™
 
Joined: Fri Dec 31, 2004 5:58 pm
Location: Lent, Netherlands

Re: class reference crashing game

Postby Mapster on Sun Mar 04, 2012 10:30 pm

The game crashes when it tries reading the reference to CItemKeyBase the class sorry, even if its just declaring it for use such as: CItemKeyBase cKeyBase;

EDIT:

Here is the .cpp.
Code: Select all
#include "cbase.h"
#include "hl2_player.h"
#include "gamerules.h"
#include "items.h"
#include "engine/IEngineSound.h"

#include "item_keys.h"

#ifdef HL2MP
#include "hl2mp_gamerules.h"
#endif

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

BEGIN_DATADESC( CItemKeyBase )
   DEFINE_KEYFIELD( m_smodel, FIELD_STRING, "model" ),
END_DATADESC();


void CItemKeyBase::Spawn( void )
{
   Precache();
   SetModel( m_smodel );
   BaseClass::Spawn();
}

void CItemKeyBase::Precache( void )
{
   PrecacheModel ( m_smodel );
   PrecacheScriptSound( "ItemBattery.Touch" );
}

bool CItemKeyBase::MyTouch( CBasePlayer *pPlayer )
{
   CBaseEntity *Key = this;
   const char *sClassname = Key->GetClassname();

   if(FStrEq(sClassname, "item_Key_Black"))
      return bGivenKey(pPlayer, SF_KEY_BLACK);
   if(FStrEq(sClassname, "item_key_Blue"))
      return bGivenKey(pPlayer, SF_KEY_BLUE);
   if(FStrEq(sClassname, "item_key_Green"))
      return bGivenKey(pPlayer, SF_KEY_GREEN);
   if(FStrEq(sClassname, "item_key_Red"))
      return bGivenKey(pPlayer, SF_KEY_RED);
   if(FStrEq(sClassname, "item_key_White"))
      return bGivenKey(pPlayer, SF_KEY_WHITE);
   if(FStrEq(sClassname, "item_key_Yellow"))
      return bGivenKey(pPlayer, SF_KEY_YELLOW);

   return false;
}

bool CItemKeyBase::bGivenKey(CBasePlayer *pPlayer, int iKey)
{
   CHL2_Player *pHL2Player = dynamic_cast<CHL2_Player *>( pPlayer );

   if (pHL2Player && pHL2Player->GiveKey( pPlayer, iKey ) )
      return true;
   else
      return false;
}

int CItemKeyBase::GetKey(int key)
{
   int iTemp = ( 1 << (key-1) );
   if ( iTemp & SF_KEY_BLACK ) return SF_KEY_BLACK;
   if ( iTemp & SF_KEY_BLUE ) return SF_KEY_BLUE;
   if ( iTemp & SF_KEY_GREEN ) return SF_KEY_GREEN;
   if ( iTemp & SF_KEY_RED ) return SF_KEY_RED;
   if ( iTemp & SF_KEY_WHITE ) return SF_KEY_WHITE;
   if ( iTemp & SF_KEY_YELLOW ) return SF_KEY_YELLOW;

   return NULL;

};

LINK_ENTITY_TO_CLASS(item_key_Black, CItemKeyBase);
LINK_ENTITY_TO_CLASS(item_key_Blue, CItemKeyBase);
LINK_ENTITY_TO_CLASS(item_key_Green, CItemKeyBase);
LINK_ENTITY_TO_CLASS(item_key_Red, CItemKeyBase);
LINK_ENTITY_TO_CLASS(item_key_White, CItemKeyBase);
LINK_ENTITY_TO_CLASS(item_key_Yellow, CItemKeyBase);
PRECACHE_REGISTER(item_key_Black);
PRECACHE_REGISTER(item_key_Blue);
PRECACHE_REGISTER(item_key_Green);
PRECACHE_REGISTER(item_key_Red);
PRECACHE_REGISTER(item_key_White);
PRECACHE_REGISTER(item_key_Yellow);


Followed by the updated .h:
Code: Select all
#ifndef ITEM_KEYS_H
#define ITEM_KEYS_H
#pragma once

#include "cbase.h"
#include "items.h"

// Max different coloured keys
#define SF_MAX_KEYS         6

enum SF_KEYS
{
   SF_KEY_BLACK      =  (1 << 17),
   SF_KEY_BLUE         =  (1 << 18),
   SF_KEY_GREEN      =  (1 << 19),
   SF_KEY_RED         =  (1 << 20),
   SF_KEY_WHITE      =  (1 << 21),
   SF_KEY_YELLOW      =  (1 << 22),
};

class CItemKeyBase : public CItem
{
   public:
      DECLARE_CLASS( CItemKeyBase, CItem );
      DECLARE_DATADESC();

      void Spawn( void );
      void Precache( void );
      bool MyTouch( CBasePlayer *pPlayer );
      bool bGivenKey(CBasePlayer *pPlayer, int iKey);

      virtual int GetKey(int key);
      virtual int GetMaxKeys() { return iMaxKeys; };

   private:
      static int const keyvalue = 00111111;
      static int const iMaxKeys = (int)SF_MAX_KEYS;

   protected:
      const char *m_smodel;
};

#endif



The hl2_player.cpp contains pHL2Player->GiveKey() which then takes it to player.cpp to give the client the item.
Code: Select all
bool CHL2_Player::GiveKey( CBasePlayer *pPlayer, int key )
{
bool CHL2_Player::GiveKey( CBasePlayer *pPlayer, int key )
{
   CItemKeyBase cKeyClass;
   int iGivenKey = key;
   int iMaxKeys = cKeyClass.GetMaxKeys();

   if(pPlayer->HasKey(iGivenKey))
      return false;

   // Give the player the key
   pPlayer->EquipKey(iGivenKey);

   for(int i=0; i<SF_MAX_KEYS; i++)
   {   DevMsg("  ||  %i",pPlayer->iGetKey(i));   }

   DevMsg("\n");

   // Play pick up sound
   CPASAttenuationFilter filter( this, "ItemBattery.Touch" );
   EmitSound( filter, entindex(), "ItemBattery.Touch" );

   return true;
}


player.h
Code: Select all
   int iGetKey( int key) {   return m_iKeys<<key; };
   bool HasKey( int key ) { if( m_iKeys & key ) return true; else return false; };
   void   RemoveKey( int key ) { m_iKeys &= ~key; };
   void   EquipKey( int key ) { m_iKeys |= key; };


EDIT2:
The keys are stored in player.h as an array which i shall now change so its using bitwise operators now btw.
Image
User avatar
Mapster
Member
Member
 
Joined: Thu Mar 01, 2012 4:07 am

Re: class reference crashing game

Postby zombie@computer on Sun Mar 04, 2012 11:41 pm

does

CItemKeyBase* cKeyBase

crash?

if not, and

CItemKeyBase cKeyBase

does, then the problem is in the constructor probably.
Im not even sure if you can LINK_ENTITY_TO_CLASS the same CItemKeyBase to different classnames, but i dont think that would cause any errors.

Is there anything you can debug? Perhaps in the constructor of CItem?
When you are up to your neck in shit, keep your head up high
zombie@computer
Forum Goer Elite™
Forum Goer Elite™
 
Joined: Fri Dec 31, 2004 5:58 pm
Location: Lent, Netherlands

Re: class reference crashing game

Postby Mapster on Wed Mar 07, 2012 6:14 am

Both of them still cause the game to crash, could it be because i have item.h in a seperate folder to the others that are trying to read it?
When i include item.h ... i have to use #include RW3D/hl2/items/items.h instead of the standard items.h command.

Just a thought though.
Image
User avatar
Mapster
Member
Member
 
Joined: Thu Mar 01, 2012 4:07 am

Re: class reference crashing game

Postby zombie@computer on Wed Mar 07, 2012 5:08 pm

no, that wont be it.

Well, i dont see anything wrong. Dont worry, even then you can still find out what is the cause.

1) set breakpoints, everywhere. See if you can get it to crash at one of those
2) start janking out lines of code untill it stops crashing
When you are up to your neck in shit, keep your head up high
zombie@computer
Forum Goer Elite™
Forum Goer Elite™
 
Joined: Fri Dec 31, 2004 5:58 pm
Location: Lent, Netherlands

Re: class reference crashing game

Postby Mapster on Sat Mar 10, 2012 7:18 am

FIXED!

When i included citem into the classes library's... it make it act AS a entity, so when i tried calling CItemKeyBase, it tried calling an entity instead of the class itself, which is why it crashed!

So instead i removed everything from there and put the main class in the .cpp and kept what i needed to be used elsewhere in that class but under a different name, also removing public CItem so it became class Class CItemKeyBase instead treating it as a library instead of an actual entity.


Thanks a lot for your help zombie@computer :)
Learned quite a fair amount from your suggestions!
Image
User avatar
Mapster
Member
Member
 
Joined: Thu Mar 01, 2012 4:07 am

Return to Programming

Who is online

Users browsing this forum: No registered users