>Do you routinely check a variable for nil to find out whether an object still exists, or do you use the Destruction callback?
You would usually check it for nil.
Some examples; Hitchecks:
pEnemy->DoEnergy(-1000000);
if(pEnemy) // not disintegrated by BFG
pEnemy->PlayOuchSound();
pEnemy->Deflect(pProjectile);
if(pProjectile) // not removed by a shield
pProjectile->Hit();
Stuff like that where you just cannot overload the object for some Destruction callback.
Are the references not using some kind of magic number? So that you can quickly see whether a reference is valid?
> pEnemy->DoEnergy(-1000000);
> if(pEnemy) // not disintegrated by BFG
> pEnemy->PlayOuchSound();
That wouldn't work because of corpses.
> pEnemy->DoEnergy(-1000000);
> if(pEnemy) // not disintegrated by BFG
> pEnemy->PlayOuchSound();
Also, calling PlayOuchSound on dead objects is harmless, because those don't play sounds. So you could simplify that to
pEnemy->DoEnergy(-1000000);
pEnemy->PlayOuchSound();
>Also, calling PlayOuchSound on dead objects is harmless, because those don't play sounds
Sorry, I thought it was clear that my "PlayOuchSound" was standing for any other arbitrary method. You could for example poison the enemy with an extremely loud and annoying "OGM YOU ARE POSION" sound. Or you could want to set a building on fire when you damaged it and it did not explode into smithereens.
>"Is the Clonk Alive()" is universal for both dead and removed Clonks.
Sure, but not for buildings or vehicles
>Unconditionally setting the building on fire works fine, even if it was removed from the landscape
Then you should probably explain to me what would actually happen if I use pObj->DoSth() and pObj is a dead reference, because I seem to have misunderstood it.
>and func DoSth2() { RemoveObject(); DoSth(); } works now.
Cool stuff. :D
Secondly, from my (CR-)scripting experience, if you are writing scripts that need to interact a lot with unknown objects - i.e., the original pack - you have to deal with the case of objects being deleted by a callback a lot. I find myself doing plenty of those if (!obj) return;- sanity checks. I do not like the idea of keeping pointers to dead objects, because that smells like trouble.
Just imagine stuff like an object creating a helper object in construction and deleting it in destruction. If a pointer to the dead version of the object is kept, the object has to assume that functions in it are executed past the Destruction callback, so it has to assure the existence of the helper in every callback.
> Go through all possible places where there can be pointers and delete them?
That would be another option. It's not as bad as it sounds - we need to denumerate all those places anyway, so the code to loop through every C4Value is already written.
But I actually want to try simply keeping those objects around and refcounting them, like arrays or strings.
> I find myself doing plenty of those if (!obj) return;- sanity checks. I do not like the idea of keeping pointers to dead objects, because that smells like trouble.
Well, my proposal would allow you to get rid of a lot of those sanity checks, because the dead object would still be around and you could do whatever you want with it. The engine has to support that today anyway, because the this pointer isn't cleared, so all engine functions already have to work on dead objects. The only sanity check needed is to ensure that the object hasn't teleported itself to 0/0 if that would affect stuff.
> If a pointer to the dead version of the object is kept, the object has to assume that functions in it are executed past the Destruction callback, so it has to assure the existence of the helper in every callback.
The helper object would stay around as long as the main object was kept around, so the main object would not need to check for it's existence. That's an improvement on the current situation, where the helper object could suddenly vanish completely without any warning.
So your stories seem to suggest that not zeroing objects would simply move the failure scenarios around. Interacting with dead objects certainly isn't the most tested corner case of the script interface, so the engine bugs would surface sooner. But as for script, whether one is surprised by a variable containing a dead object or a variable containing nil doesn't make a huge difference.
It might be too late to change this because a lot of script already relies on the current behaviour, but perhaps we can still make the change internally and hide it by making dead objects evaluate to false. Probably an experimental implementation to see what breaks is called for.
>That's an improvement on the current situation, where the helper object could suddenly vanish completely without any warning.
Uh, no. The helper could still suddenly vanish without any warning but you would notice it at a different place. Or did I get you wrong?
Do you mean that it is an improvement because you would "have" to implement an destruction callback (maybe even with an appendto to the script) because otherwise nothing would work?
Then your improvement would be as much of an improvement as an entry to the docs saying "Please use a callback based architecture between your objects", imo
Just about any object interaction would need to check for dead objects (just like the engine does all those status-checks) AND still check for zero pointers in most cases.
> Projectiles and weapons shouldn't hit dead objects. Floor switches shouldn't be affected by dead objects.
Those would use FindObject and not be affected either way.
> Animals shouldn't follow dead objects.
They shouldn't follow objects that are simply out of reach in other ways either. Checking for Teleportation or for the objects not being Alive() automatically covers dead objects.
> Fire should stop burning when its object is dead
Effects rely on callbacks for that, or for the effect to simply be removed with the object.
> and dead objects shouldn't be able to catch fire again.
They can't get effects, so that's already covered.
> Just about any object interaction would need to check for dead objects (just like the engine does all those status-checks) AND still check for zero pointers in most cases.
Well, not in the examples you listed. Also, checking for nullpointers would only be required if you want to guard against some other script tampering with your local variables. In my opinion, it's the responsibility of the script setting a variable to ensure that nothing bad happens. So if your interaction consists of obj->SetRDir(), you now need to check for nullpointers, but you don't need to do that anymore with the proposed change, because SetRDir() is harmless on dead objects.
>because SetRDir() is harmless on dead objects.
What would those "dead objects" be? I think I could have misunderstood you.
If an object is removed and the locals holding a reference to said object are not automatically set to zero, the object is considered "dead", right? And when SetRDir internally tries to deference the handler it would notice that some magic number (?) does not fit anymore and the object does not exist anymore and therefore do nothing?
That's how I understood that so far.
(Because using "dead" as "not alive" would not make much sense since objects or vehicles are never alive but can still break after damage)
this->Explode(); this->MakeCrewMember();
or similar things.
There's a field named Status in every object that tracks whether the object has been removed. It's also used for ScenarioSections for some reason, so you can call GetObjectStatus to verify that this->Explode() does indead remove this.
>There's a field named Status in every object that tracks whether the object has been removed. It's also used for ScenarioSections for some reason, so you can call GetObjectStatus to verify that this->Explode() does indead remove this.
Wouldn't it then be possible to let the reference evaluate to false when cast to bool?
Okay, I think obj>0 actually already throws at runtime, but there are more complex examples. It's not impossible, I'm just not sure whether it's worth the effort.
And the function to check Status is already called GetObjectStatus. We might want to introduce a shorter alias, though.
Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill