Game Development Community

Weapon Trigger State

by Robert Fritzen · in Torque 3D Professional · 04/01/2014 (8:38 am) · 10 replies

I've got something that seems like it should be easy to do, but for some reason, it's not working out.

I need to assess the current state of a source object's fire trigger for my current work. and I've got something along the lines of this:

if(mSourceObject.getObject()->getImageTriggerState(0) == true) {
   //do stuff
}

Unfortunately, this statement evaluates to false every time, even when the fire trigger is down. I can confirm that mSourceObject is indeed the object in question here, and using %obj.getImageTrigger(0); in TS evaluates to the correct value.

Any ideas here?

EDIT: While I'm here with it, I need a way to delete an object from it's advanceTime call that won't cause me a lovely access violation after the object is deleted.

#1
04/01/2014 (10:04 am)
The deletion of ITickable objects causing segfault in advanceTime() was fixed in pull request #529. Sounds like the same problem for regular SimObjects. I think the problem is that you're not suppose to be able to just delete an object like that, but instead use SimObject::safeDeleteObject() method.
#2
04/01/2014 (12:56 pm)
That appears to have stopped the crashing upon deletion, however a crash still occurs about 15 - 30 seconds post deletion now.
#3
04/02/2014 (8:05 am)
Anyone have any ideas on my two problems here, I'd really like to get this working sooner, rather than later so I can get to work on some more important things.

EDIT: If it at all helps, this is the access violation occurring, and this always happens about 20 - 30 seconds after the projectile object is deleted via safeDeleteObject();

First-chance exception at 0xfeeefeee in Tactical Uprising Beginnings.exe: 0xC0000005: Access violation.
Unhandled exception at 0xfeeefeee in Tactical Uprising Beginnings.exe: 0xC0000005: Access violation reading location 0xfeeefeee.
#4
04/02/2014 (1:24 pm)
Have you checked that the getObject() part returns the right object?
#5
04/02/2014 (1:34 pm)
I have confirmed that mSourceObject.getObject() is the correct object.

In fact here's the full "if":

if(mSourceObject.getObject() != NULL) {
		Con::printf("Check Trigger: SRC: %i, TRIG: %i", mSourceObject.getObject()->getId(), mSourceObject.getObject()->getImageTriggerState(0) ? 1 : 0);
		if(mSourceObject.getObject()->getImageTriggerState(0) == true) {

The echo always shows the correct ID number for my player object when firing, but the TRIG: always evals to 0, which is false. The correct result should be that as long as the trigger is "held", that should be returning a 1 (true).

No idea about the crashing either.

The processing of this is handled in ::advanceTime(), I have tried to use ::processTick() but it never evaluates beyond the first "tick", afterwards the thing appears to "die" and never get called again.
#6
04/02/2014 (5:53 pm)
Are you setting mSourceObject to NULL equivalent after you do .safeDeleteObject()?
#7
04/04/2014 (4:31 pm)
Since this is a projectile class, and it inherits projectile, that should be handled...

This is the last reference to mSourceObject made by the projectile through the code that I am aware of.

void BeamProjectile::onRemove() {
	if(mSourceObject.getObject()) {
	   mSourceObject.getObject()->setDataField(StringTable->insert("firingBeam"), NULL, "0"); 
	}
   Parent::onRemove();
}
#8
04/07/2014 (7:54 am)
Ok, I'm obviously going to have to dig deeper here because it seems like everything that should be the problem, isn't the problem.

Even doing the following:
BeamProjectile::~BeamProjectile() {
	mSourceObject = NULL;
	mTarget = NULL;
}

Does not stop the crashing of the client 20 so seconds after safeDeleteObject().

What I want to know now, is what is the exact order of function calls after safeDeleteObject is triggered, I want to pin down the location of this crash exactly. If anything else seems like it would be causing this, please let me know. I really need to get this fixed and working.

EDIT: This is just weird, I added debug echos to pretty much the beginning and end of every single function, and I can confirm that all calls to advanceTime() halt as soon as deleteObject() is called, followed by onRemove and the destructor, which is exactly as it should. No further calls within the projectile are made, so this has something to do outside of the projectile, but related to it somehow. Any help here would be greatly appreciated.

EDIT 2: Ok, I've narrowed it down a bit further. It has something to do with deleting objects within the advanceTime call. I've moved all of my code into processTick() / simulate() and no crash. I should mention that this crash occurs even after applying the git change mentioned above and using safeDeleteObject(), so further investigation on that git change might be needed.

So, for the time being I'd like to focus on the original question posed, regarding the trigger state function.
#9
04/08/2014 (5:59 am)
Just curious, what's the significance of using mSourceObject.getObject()->getImageTriggerState(0) instead of mSourceObject->getImageTriggerState(0)? Since you've verified the object, it cant be timing out.

Part2: advanceTime() runs on the server and on the client. Is the crash the result of deleting the object in both? If you delete the object on the server won't the networking code remove the ghosts?
#10
04/08/2014 (7:45 am)
I was using .getObject() because for some reason when I was running object tests in my firing code, using mSourceObject alone would result in the projectile slipping through the:

if(mSourceObject) {

call on the first run through of the code. I'll try removing the getObject() part and test without it, but I highly doubt that will change anything.

As for advance time, would it work if I simply added a: if(isServerObject()) prior to the deletion clause so it only deletes on the server?

EDIT: And I was right, no change without .getObject(). This is really starting to get pretty high up there with "confusing" stuff in this engine. My trigger echo is triggered in the C++ with this:

Con::printf("Check Trigger: SRC: %i, TRIG: %i", mSourceObject.getObject()->getId(), mSourceObject->getImageTriggerState(0) ? 1 : 0);

And on the torque script side of things, I have this in onFire(){

echo("onFire: "@%slot@" => "@%obj.getImageTrigger(%slot));

Which is a code called in the shapeBase.cpp file that has this line:
return object->getImageTriggerState(slot);

And I have already confirmed from the debug echos that both the slot of the gun, and the source object match in both C++ and TS, the only difference here, being that the result of C++ is always false, where TS returns true properly.

TS: onFire: 0 => 1
C++: Check Trigger: SRC: 6877, TRIG: 0

So, what exactly is going on here?

EDIT 2: I'm an idiot... I really should have done this earlier. I attached the object ID to the TS as well, and surprise surprise, they're different. Apparently this whole time, I've been reading off of the client player object instead of the server player object.

How can I go about fixing that?