Game Development Community

Extending Player class

by Marton Gyorgy · in Torque 3D Professional · 05/22/2011 (3:26 pm) · 7 replies

I am trying to extend the player class to change how it works. I tried to make a TestPlayer class that inherits from Player class (and changes nothing). Code compiled and I could create a TestPlayer with a TestPlayerDatablock and it worked but when I tried to exit from the game I got the standard error when a program fails and stops in Windows XP.

My testPlayer.h code is:
//-----------------------------------------------------------------------------
// Torque 3D
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#ifndef _TESTPLAYER_H_
#define _TESTPLAYER_H_

#ifndef _PLAYER_H_
#include "T3D/player.h"
#endif
//----------------------------------------------------------------------------

struct TestPlayerData: public PlayerData {
   typedef PlayerData Parent;
   DECLARE_CONOBJECT(TestPlayerData);
   TestPlayerData();
};


class TestPlayer: public Player
{
   typedef Player Parent;
public:
   DECLARE_CONOBJECT(TestPlayer);

   TestPlayer();
   ~TestPlayer();
};


#endif

testPlayer.cpp:
//-----------------------------------------------------------------------------
// Torque 3D
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#include "platform/platform.h"
#include "T3D/testPlayer.h"

#include "platform/profiler.h"
#include "math/mMath.h"
#include "math/mathIO.h"
#include "core/stringTable.h"
#include "core/stream/bitStream.h"
#include "core/dnet.h"
#include "console/simBase.h"
#include "console/console.h"
#include "console/consoleTypes.h"
#include "collision/extrudedPolyList.h"
#include "collision/clippedPolyList.h"
#include "collision/earlyOutPolyList.h"
#include "ts/tsShapeInstance.h"
#include "sfx/sfxSystem.h"
#include "sfx/sfxProfile.h"
#include "sfx/sfxSource.h"
#include "sceneGraph/sceneGraph.h"
#include "sceneGraph/sceneState.h"
#include "environment/waterBlock.h"
#include "app/game.h"
#include "T3D/gameConnection.h"
#include "T3D/trigger.h"
#include "T3D/physicalZone.h"
#include "T3D/item.h"
#include "T3D/missionArea.h"
#include "T3D/fx/particleEmitter.h"
#include "T3D/fx/cameraFXMgr.h"
#include "T3D/fx/splash.h"
#include "T3D/tsStatic.h"
#include "T3D/physics/physicsPlugin.h"
#include "T3D/physics/physicsPlayer.h"
#include "T3D/decal/decalManager.h"
#include "T3D/decal/decalData.h"
//----------------------------------------------------------------------------

IMPLEMENT_CO_DATABLOCK_V1(TestPlayerData);

TestPlayerData::TestPlayerData()
{
	Parent::PlayerData();
}

//----------------------------------------------------------------------------

IMPLEMENT_CO_NETOBJECT_V1(TestPlayer);

TestPlayer::TestPlayer()
{
	Parent::Player();
}

TestPlayer::~TestPlayer()
{
	Parent::~Player();
}

#1
05/22/2011 (4:21 pm)
If you run this in the debugger, where does it come down? (i.e. what does the callstack window give you)
#2
05/23/2011 (1:44 am)
It's crashing because you're calling Parent::~Player in the destructor. The WeakRefBase class from which all game objects are derived defines its destructor as virtual, which means that the parent destructor will be called automatically for derived classes. There's also no need to explicitly call the default constructor for the parent as that is automatically called for derived classes.

One other thing, because you want your class to use a new datablock class is to make sure this datablock actually gets assigned to your object, and to do that you need to override onNewDataBlock.

testPlayer.h
#ifndef _TESTPLAYER_H_
#define _TESTPLAYER_H_

#ifndef _PLAYER_H_
#include "T3D/player.h"
#endif
//----------------------------------------------------------------------------

struct TestPlayerData: public PlayerData {
   typedef PlayerData Parent;
   DECLARE_CONOBJECT(TestPlayerData);
   TestPlayerData();
};


class TestPlayer: public Player
{
   typedef Player Parent;
   
   TestPlayerData *mDataBlock; // use our new datablock type

public:
   DECLARE_CONOBJECT(TestPlayer);

   TestPlayer();
   ~TestPlayer();

   // override onNewDataBlock so we can use our new datablock type
   bool onNewDataBlock(GameBaseData* dptr, bool reload); 
};

#endif


testPlayer.cpp
#include "T3D/testPlayer.h"
//----------------------------------------------------------------------------

IMPLEMENT_CO_DATABLOCK_V1(TestPlayerData);

TestPlayerData::TestPlayerData()
{
   // initialize variables when you have some
}

//----------------------------------------------------------------------------

IMPLEMENT_CO_NETOBJECT_V1(TestPlayer);

TestPlayer::TestPlayer()
{
   mDataBlock = 0; // we don't have a datablock yet
}

TestPlayer::~TestPlayer()
{
   // nothing to do here atm
}

// set up the datablock
bool TestPlayer::onNewDataBlock(GameBaseData* dptr, bool reload)
{
   mDataBlock = dynamic_cast<TestPlayerData*>(dptr);
   if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload))
      return false;
   
   scriptOnNewDataBlock();
   return true;
}
#3
05/23/2011 (1:55 am)
Yes, it was the desctructor. I implement onNewDataBlock then, thanks!
#4
05/23/2011 (2:04 am)
I think you should not include the reload variable in the onNewDataBlock just
bool onNewDataBlock(GameBaseData* dptr);
#5
05/23/2011 (3:44 am)
Which version of T3D are you using? The reload variable is needed for the latest versions (1.1Beta3 or 1.1Preview), but not for some of the older versions.
#6
05/23/2011 (4:49 am)
Yes, I use the older 1.0.1 version.
#7
05/23/2011 (7:15 am)
AIPlayer is a good example of a class that extends the Player class.