• Please make sure you are familiar with the forum rules. You can find them here: https://forums.tripwireinteractive.com/index.php?threads/forum-rules.2334636/

Code Extending ROPawn issue

Morning,

I have a custom pawn class that extends ROPawn as I want to override a couple of functions, but it's basically just a shell right now with some logging:
Code:
class FTPawn extends ROPawn;

function bool Died(Controller Killer, class<DamageType> damageType, vector HitLocation)
{
	`Log(">>> DEBUG : Pawn Died", , 'FTPawn');

       super.Died(Killer, damageType, HitLocation);
}

DefaultProperties
{
}

I also have the following set in my main game class default properties to ensure my pawn class gets used:
Code:
AIPawnClass=class'TOGAFT.FTPawn'
DefaultPawnClass=class'TOGAFT.FTPawn'

This is the same way I have my game mode setup in the UDK version I did a while back.

However, my pawn class is not getting used like it does in the UDK. The gameclass is still somehow using ROPawn instead.

All my other custom classes that extend/override are being used correctly, just not my pawn class :confused:

Any thoughts?
 
I don't expect that those "default pawn class" settings are ever used for anything. ROPawns are never spawned by the game, and if you're extending something off of those, I doubt they'd work right anyway, because it's two steps up in the hierarchy from the ones the game uses.

The actual character objects spawned by the game are one of the ROGameContent.RO(Allied|Axis)PawnLevel(#)(Role) classes, retrieved from settings in the ROGameInfo. Do the console command "getall ROPawn class" on a live server to see an example.

If you want to change which classes get spawned, the ROGameInfo is the place to start. You might be able to just find the current instance, edit its variables at runtime, and be done with it nice and cleanly.

And yes, that means that overriding pawn behavior requires you to subclass every single one of the existing ones. All 300 of them. Just like I had to do 91 subclasses of the bullets and weapons for Antilag. Be prepared to get very familiar with the UnrealScript preprocessor :)

It's a pain in the butt and it makes your final filesize proportionally larger, so it's worth the while to try to do it in any other way possible. Your Died override is better off done in the mutator PreventDeath hook, for instance.
 
Upvote 0
A preprocessor is a system that skims and edits the code files before they're fed to the compiler. All those `ifdef lines you see sprinkled all over the stock code are preprocessor commands.

Of note in this case is that you can use the preprocessor to shortcut the class-building for you. You can leave all your code in one easy-to-maintain file and simply have the preprocessor insert it automatically into a bunch of files that are so small & simple that you can just make them once (ideally with a script or batch file) and then never have to touch them again. In short, you make the skeleton, and let the computer do the work of fleshing it out.

...because keeping up that many classes by hand is insanity.
 
Upvote 0
That's the gist of it, yep. You could also use preprocessor macros to make sure that any variables or function calls get tailored to the file as well, or to make sure that some sections show up only in some files. It's a simple preprocessor, compared to some full-blown languages out there, but it's still capable of powerful things that can save you a lot of time and hassle.
 
Last edited:
Upvote 0
Yep. I can post the Antilag source, if you want to see a (less in)convenient way of building the preprocessor skeleton for that, so you can let the make process handle the upkeep for you.

But there's a mutator hook for TakeDamage too: Mutator.NetDamage. It's still live in ROPawn.

Would you mind posting your source? I'd be also interested to see how you did it.
 
Upvote 0
Right, thought id post back in this thread as it's relevant to my current issue...

As mentioned above, I have created a bunch of classes that extend each of the games player class (AxisPawnLevel1Eng, AxisPawnLevel2Eng etc), each of which has an include so they all run some common code which works fine.

Now when in-game, when I aim down my sights and press my use key, If I am looking at a team mate that is in a certain state, I need to set a variable on that players custom pawn class (which ever one it may be).

I have done the trace code and it writes some debug info to screen:
Code:
ClientMessage("Hit: "$HitActor$"  class: "$HitActor.class.outer.name$"."$HitActor.class);

Would write out something like:
Code:
Hit: FTAxisPawnLevel1Engineer etc

How can I set a variable if the class could be one of several possible classes?

If this were c# I would have created an interface which each of my custom class inherits so I could call it with confidence...

I could of course have a rather large case statement doing IsA('FTblah...') and then just cast it, but i'm hoping there is a more quick way.

Any thoughts appreciated :)
 
Upvote 0
Think I must be being thick here...

I have created an interface called FTPawnIntf and defined a function inside it and then added that to all my custom pawn classes.

Code:
interface FTPawnIntf;

function TestInterface();

and

Code:
class FTAxisPawnLevel6SquadLeaderW extends ROAxisPawnLevel6SquadLeaderW implements(FTPawnIntf);

If I try a compile without adding the function defined in my interface to the custom pawn class, I get the expect errors, so I know that works.

So I implement my Interface function inside the custom pawn class and it compiles without error :)

Next in my player controller class I need to test for the interface which I try and do like so:
Code:
if ( FTPawnIntf(HitActor) != none)
{
     // do stuff here....
}

and according to this tutorial, this should work:
Code:
local FTPawnIntf myIntf;

myIntf = FTPawnIntf(HitActor);

if ( myIntf != none)
{
     // do stuff here....
}

Upon compiling I get the following error:
Code:
Error, Missing opening '(' in Implements list

According to the documentation, the above should work:
http://udn.epicgames.com/Three/UnrealScriptInterfaces.html

My eyes have glazed over lol :D
 
Last edited:
Upvote 0
In case of interfaces, then you need to make a reference to your interface. You will get something like:

Code:
class FTAxisPawnLevel6SquadLeaderW extends ROAxisPawnLevel6SquadLeaderW implements(FTPawnIntf);

var FTPawnIntf  [COLOR=Yellow]IntRef[/COLOR];

function BlaBlaBla(Actor HitActor)
{
    if ([COLOR=Yellow]IntRef[/COLOR](HitActor) != none)
    {
        // do stuff here....
    }
}
This line if (IntRef(HitActor) != none) is not a typo ;)
 
Last edited:
Upvote 0