Jump to content
sukhoi191

Accessing the position of "CraterOnVehicle" causes the game to crash

Recommended Posts

I'm probably about 20 years too late for sending OFP / CWA bug reports but here I am, doing just that.

 

Now, to be serious, I'm hoping someone might give me some idea why is it happening. To reproduce a crash, simply try to execute the following script:

crater = "CraterOnVehicle" createVehicle [0,0,0]
craterPosition = getPos crater

What causes the crash specifically is the "getPos crater" function call. Judging by the crash dump, the game tries to access a NULL pointer. It doesn't matter what position you provide for the instance.

 

It may seem like I'm really trying to find problems but it's actually a result of a thorough analysis of CWA crashes I got.

 

Recently, me and my friend happened upon some great crCTI missions. The only download link I could find is here if anyone's interested. After playing for some time on vanilla CWA I decided to try them out on FFUR 2007, specifically FFUR-SLX 2007 2.5.

 

In the crCTI missions I mentioned there is a function "Common\InForest.sqf" which contains a "while" loop. It seems to work like the "nearestObjects" known from ArmAs. In CWA, only "nearestObject" (singular) is available so it makes sense to write your own implementation of "nearestObjects" if you need it.

 

To keep things short, here's the important part:

while "_i < 100 && _c < 4" do
{
  _dist = 30*(_i/100);
  _dir = _i*20;
  _pos = [ _this select 0, [_dist*(sin _dir), _dist*(cos _dir)] ] call funcVectorAdd;
  // "Art0" setMarkerPos _pos;
  _object = nearestObject [_pos, ""]; // this is important

...and then:

if (((getPos _object) select 2) > 5) then

To summarize:

  1. "_object = nearestObject [_pos, ""]" might find an instance of "CraterOnVehicle" (which seems to happen regularly on FFUR but never on vanilla).
  2. "getPos _object" in the "if" condition causes a crash when _object is a "CraterOnVehicle" instance.

I have a theory why these crashes occur on FFUR 2007, but not on vanilla: FFUR adds much more effects like flames and smoke. Perhaps it is creating "CraterOnVehicles" instances more freely than vanilla, and so the "while" loop is much more likely to find one.

 

I know it can be easily fixed by skipping "CraterOnVehicle" instances in the while loop, I'm just curious if anyone has any idea why is it happening in the first place? Also, I was able to find more objects causing the same crash (e.g. "Crater") so knowing the reason for this issue would be very helpful in pinpointing any other potential trouble-makers which should be excluded from the loop.

 

Here's how they both look like in config.cpp:

class Crater
{
    model="";
    simulation="Crater";
};

class CraterOnVehicle
{
    model="";
    simulation="CraterOnVehicle";
};

Obviously, my first idea was that the "model" is empty so maybe this was the culprit, but I quickly found an example proving otherwise:

class Track
{
    model="";
    simulation="track";
};

When I create an instance of "Track" and call "getPos" on it, it correctly returns the position, so empty "model" isn't the reason (at least not by itself).

  • Like 1

Share this post


Link to post
Share on other sites

I also recently found a bug with getPos "CraterOnVehicle". It can be bypassed using the command getPosASL "CraterOnVehicle".

Objects class "Crater" / "Track" /  "Mark" are placed on the ground surface, their vertical position (getPos select 2) is always = 0.

But the "CraterOnVehicle" has a vertical position relative to the ground surface > 0. It seems that game engine cannot calculate getPos "CraterOnVehicle" select 2 and crashes.

  • Like 1

Share this post


Link to post
Share on other sites

Thanks for the info, that's interesting. I took all the class names from CfgNonAIVehicles and repeated the same test just to see which ones will crash, which will retain position Z, and which will reset to [0,0,0]. Here's the results:

 

Spoiler

Crash when "getPos" is called: "SmokeSource", "Crater", "CraterOnVehicle", "Slop", "DynamicSound", "Smoke"

 

Crash when trying to create an instance with "createVehicle": "StreetLamp", "StreetLampWood", "StreetLampMetal", "ProxyFlag"

 

No crash, position is reset to [0,0,0]: "Track", "Mark", "ObjectDestructed", "Explosion", "SoundOnVehicle", "ThunderBolt", "EditCursor", "ObjView", "Temp", "ProxyAT1_Proxy", "ProxyMaverik_Proxy", "ProxyAmmoInTruck", "ProxyScud_Strela_Proxy"

 

No crash, position is reset to [0,0,0] and an error popup is shown:

  • "ProxyAmmo_Bedna_In" ("Cannot open object data3d\ammo_bedna_in.p3d")
  • "ProxyAmmo_Bedna2" ("Cannot open object data3d\ammo_bedna2.p3d")

No crash, position is mostly retained (sometimes Z is higher or lower than the one provided to createVehicle): "EmptyDetector", "SeaGull", "Camera", "ProxyWeapon", "ProxySecWeapon", "ProxyAK_47_Proxy", "ProxyAK_47_v58_Proxy", "ProxyAK_47_granatomet_Proxy", "ProxyRPG7_Proxy", "ProxyLAW_Proxy", "ProxyStinger_Proxy", "ProxyCrew", "ProxyCommander", "ProxyDriver", "ProxyGunner", "ProxyCargo", "ProxyM60Commander", "ProxyM60Driver", "ProxyM60Gunner", "ProxyM60CommanderOut", "ProxyM60DriverOut", "ProxyM60GunnerOut", "ProxyM1A1Commander", "ProxyM1A1Driver", "ProxyM1A1Gunner", "ProxyM1A1CommanderOut", "ProxyM1A1DriverOut", "ProxyM1A1GunnerOut", "ProxyM113Commander", "ProxyM113Driver", "ProxyM113Gunner", "ProxyM113CommanderOut", "ProxyM113DriverOut", "ProxyM113GunnerOut", "ProxyBMPCommander", "ProxyBMPDriver", "ProxyBMPGunner", "ProxyBMPCommanderOut", "ProxyBMPDriverOut", "ProxyBMPGunnerOut", "ProxyT72Commander", "ProxyT72Driver", "ProxyT72Gunner", "ProxyT72CommanderOut", "ProxyT72DriverOut", "ProxyT72GunnerOut", "ProxyT80Commander", "ProxyT80Driver", "ProxyT80Gunner", "ProxyT80CommanderOut", "ProxyT80DriverOut", "ProxyT80GunnerOut", "ProxyZSUCommander", "ProxyZSUDriver", "ProxyZSUGunner", "ProxyZSUCommanderOut", "ProxyZSUDriverOut", "ProxyZSUGunnerOut", "ProxyT55Commander", "ProxyT55Driver", "ProxyT55Gunner", "ProxyT55CommanderOut", "ProxyT55DriverOut", "ProxyT55GunnerOut", "ProxyMedic", "ProxyNemocnej", "ProxyUH60Pilot", "ProxyUH60CoPilot", "ProxyUH60Gunner", "ProxyMi17Pilot", "ProxyMi17CoPilot", "ProxyMi24Pilot", "ProxyMi24Gunner", "ProxyAH1Pilot", "ProxyAH1Gunner", "ProxyAH1GunnerStat", "ProxyA10Pilot", "ProxyCesnaPilot", "ProxyCesnaCoPilot", "ProxyCesnaCargo", "ProxyTraktorDriver", "ProxyJeepDriver", "ProxyJeepGunner", "ProxyJeepCoDriver", "ProxyJeepCoDriverBack", "Proxy5tDriver", "Proxy5tCoDriver", "ProxyUazDriver", "ProxyUazCoDriver", "ProxyUralDriver", "ProxyUralCoDriver", "ProxySkodaDriver", "ProxySkodaCoDriver", "ProxySkodaCoDriverBack", "ProxyV3SDriver", "ProxyV3SCoDriver", "ProxyPBRDriver", "ProxyPBRGunner", "ProxyHRLDriver", "ProxyHRLGunner", "ProxySCUDDriver", "ProxySCUDCoDriver", "ProxyParasutista", "ProxyM2Gunner", "ProxyPKGunner", "ProxyFlag_Auto", "ProxyFlag_Alone", "ProxyFlag_Alone_Big", "ProxyFlag_Vojak", "ProxyFlag_Stozar", "ProxyFlag_Plane", "ProxyFlag_Plane_Big"

 

It looks like it's safe to use getPos as long as you avoid a couple of specific classes. Of course, it's possible that there are other classes which will cause the crash (I tested only the ones in CfgNonAIVehicles) but for now it should be enough to fix the mission.

 

If anyone wants to check it out, here's the script I used:

 

Spoiler

; Any physical object created in the editor will do.
_object = _this select 0

; Position Z is set to 5 to check if it will be retained.
_position = [position _object select 0, position _object select 1, 5]

; Delete the original object to avoid collisions which could impact positions.
deleteVehicle _object

; This is an array with all class names present in vanilla CfgNonAIVehicles
_allNonAiVehicles = ["EmptyDetector", "Track", "Mark", "SmokeSource", "ObjectDestructed", "Explosion", "Crater", "CraterOnVehicle", "Slop", "Smoke", "DynamicSound", "StreetLamp", "StreetLampWood", "StreetLampMetal", "SoundOnVehicle", "ThunderBolt", "EditCursor", "ObjView", "Temp", "SeaGull", "Camera", "ProxyWeapon", "ProxySecWeapon", "ProxyAK_47_Proxy", "ProxyAK_47_v58_Proxy", "ProxyAK_47_granatomet_Proxy", "ProxyRPG7_Proxy", "ProxyLAW_Proxy", "ProxyStinger_Proxy", "ProxyAT1_Proxy", "ProxyMaverik_Proxy", "ProxyScud_Strela_Proxy", "ProxyCrew", "ProxyCommander", "ProxyDriver", "ProxyGunner", "ProxyCargo", "ProxyM60Commander", "ProxyM60Driver", "ProxyM60Gunner", "ProxyM60CommanderOut", "ProxyM60DriverOut", "ProxyM60GunnerOut", "ProxyM1A1Commander", "ProxyM1A1Driver", "ProxyM1A1Gunner", "ProxyM1A1CommanderOut", "ProxyM1A1DriverOut", "ProxyM1A1GunnerOut", "ProxyM113Commander", "ProxyM113Driver", "ProxyM113Gunner", "ProxyM113CommanderOut", "ProxyM113DriverOut", "ProxyM113GunnerOut", "ProxyBMPCommander", "ProxyBMPDriver", "ProxyBMPGunner", "ProxyBMPCommanderOut", "ProxyBMPDriverOut", "ProxyBMPGunnerOut", "ProxyT72Commander", "ProxyT72Driver", "ProxyT72Gunner", "ProxyT72CommanderOut", "ProxyT72DriverOut", "ProxyT72GunnerOut", "ProxyT80Commander", "ProxyT80Driver", "ProxyT80Gunner", "ProxyT80CommanderOut", "ProxyT80DriverOut", "ProxyT80GunnerOut", "ProxyZSUCommander", "ProxyZSUDriver", "ProxyZSUGunner", "ProxyZSUCommanderOut", "ProxyZSUDriverOut", "ProxyZSUGunnerOut", "ProxyT55Commander", "ProxyT55Driver", "ProxyT55Gunner", "ProxyT55CommanderOut", "ProxyT55DriverOut", "ProxyT55GunnerOut", "ProxyMedic", "ProxyNemocnej", "ProxyUH60Pilot", "ProxyUH60CoPilot", "ProxyUH60Gunner", "ProxyMi17Pilot", "ProxyMi17CoPilot", "ProxyMi24Pilot", "ProxyMi24Gunner", "ProxyAH1Pilot", "ProxyAH1Gunner", "ProxyAH1GunnerStat", "ProxyA10Pilot", "ProxyCesnaPilot", "ProxyCesnaCoPilot", "ProxyCesnaCargo", "ProxyTraktorDriver", "ProxyJeepDriver", "ProxyJeepGunner", "ProxyJeepCoDriver", "ProxyJeepCoDriverBack", "Proxy5tDriver", "Proxy5tCoDriver", "ProxyUazDriver", "ProxyUazCoDriver", "ProxyUralDriver", "ProxyUralCoDriver", "ProxySkodaDriver", "ProxySkodaCoDriver", "ProxySkodaCoDriverBack", "ProxyV3SDriver", "ProxyV3SCoDriver", "ProxyPBRDriver", "ProxyPBRGunner", "ProxyHRLDriver", "ProxyHRLGunner", "ProxySCUDDriver", "ProxySCUDCoDriver", "ProxyParasutista", "ProxyM2Gunner", "ProxyPKGunner", "ProxyFlag", "ProxyFlag_Auto", "ProxyFlag_Alone", "ProxyFlag_Alone_Big", "ProxyFlag_Vojak", "ProxyFlag_Stozar", "ProxyFlag_Plane", "ProxyFlag_Plane_Big", "ProxyAmmoInTruck", "ProxyAmmo_Bedna_In", "ProxyAmmo_Bedna2"]

; These classes crash when "getPos" is called on their instances.
_crashingWhenGetPosCalled = ["SmokeSource", "Crater", "CraterOnVehicle", "Slop", "DynamicSound", "Smoke"]

; These classes crash when you try to create an instance with "createVehicle".
_crashingWhenCreatingInstance = ["StreetLamp", "StreetLampWood", "StreetLampMetal", "ProxyFlag"]

; These classes don't crash and (mostly) retain all original position values.
_nonCrashingThatRetainPositionZ = ["EmptyDetector", "SeaGull", "Camera", "ProxyWeapon", "ProxySecWeapon", "ProxyAK_47_Proxy", "ProxyAK_47_v58_Proxy", "ProxyAK_47_granatomet_Proxy", "ProxyRPG7_Proxy", "ProxyLAW_Proxy", "ProxyStinger_Proxy", "ProxyCrew", "ProxyCommander", "ProxyDriver", "ProxyGunner", "ProxyCargo", "ProxyM60Commander", "ProxyM60Driver", "ProxyM60Gunner", "ProxyM60CommanderOut", "ProxyM60DriverOut", "ProxyM60GunnerOut", "ProxyM1A1Commander", "ProxyM1A1Driver", "ProxyM1A1Gunner", "ProxyM1A1CommanderOut", "ProxyM1A1DriverOut", "ProxyM1A1GunnerOut", "ProxyM113Commander", "ProxyM113Driver", "ProxyM113Gunner", "ProxyM113CommanderOut", "ProxyM113DriverOut", "ProxyM113GunnerOut", "ProxyBMPCommander", "ProxyBMPDriver", "ProxyBMPGunner", "ProxyBMPCommanderOut", "ProxyBMPDriverOut", "ProxyBMPGunnerOut", "ProxyT72Commander", "ProxyT72Driver", "ProxyT72Gunner", "ProxyT72CommanderOut", "ProxyT72DriverOut", "ProxyT72GunnerOut", "ProxyT80Commander", "ProxyT80Driver", "ProxyT80Gunner", "ProxyT80CommanderOut", "ProxyT80DriverOut", "ProxyT80GunnerOut", "ProxyZSUCommander", "ProxyZSUDriver", "ProxyZSUGunner", "ProxyZSUCommanderOut", "ProxyZSUDriverOut", "ProxyZSUGunnerOut", "ProxyT55Commander", "ProxyT55Driver", "ProxyT55Gunner", "ProxyT55CommanderOut", "ProxyT55DriverOut", "ProxyT55GunnerOut", "ProxyMedic", "ProxyNemocnej", "ProxyUH60Pilot", "ProxyUH60CoPilot", "ProxyUH60Gunner", "ProxyMi17Pilot", "ProxyMi17CoPilot", "ProxyMi24Pilot", "ProxyMi24Gunner", "ProxyAH1Pilot", "ProxyAH1Gunner", "ProxyAH1GunnerStat", "ProxyA10Pilot", "ProxyCesnaPilot", "ProxyCesnaCoPilot", "ProxyCesnaCargo", "ProxyTraktorDriver", "ProxyJeepDriver", "ProxyJeepGunner", "ProxyJeepCoDriver", "ProxyJeepCoDriverBack", "Proxy5tDriver", "Proxy5tCoDriver", "ProxyUazDriver", "ProxyUazCoDriver", "ProxyUralDriver", "ProxyUralCoDriver", "ProxySkodaDriver", "ProxySkodaCoDriver", "ProxySkodaCoDriverBack", "ProxyV3SDriver", "ProxyV3SCoDriver", "ProxyPBRDriver", "ProxyPBRGunner", "ProxyHRLDriver", "ProxyHRLGunner", "ProxySCUDDriver", "ProxySCUDCoDriver", "ProxyParasutista", "ProxyM2Gunner", "ProxyPKGunner", "ProxyFlag_Auto", "ProxyFlag_Alone", "ProxyFlag_Alone_Big", "ProxyFlag_Vojak", "ProxyFlag_Stozar", "ProxyFlag_Plane", "ProxyFlag_Plane_Big"]

; These classes don't crash and "getPos" always returns [0,0,0].
_nonCrashingThatResetPositionZTo000 = ["Track", "Mark", "ObjectDestructed", "Explosion", "SoundOnVehicle", "ThunderBolt", "EditCursor", "ObjView", "Temp", "ProxyAT1_Proxy", "ProxyMaverik_Proxy", "ProxyAmmoInTruck", "ProxyScud_Strela_Proxy"]

; These classes don't crash, "getPos" always returns [0,0,0], and there is an additional popup error when you create their instance with "createVehicle".
; "ProxyAmmo_Bedna_In" - popup "Cannot open object data3d\ammo_bedna_in.p3d"
; "ProxyAmmo_Bedna2" - popup "Cannot open object data3d\ammo_bedna2.p3d"
_specialCases = ["ProxyAmmo_Bedna_In", "ProxyAmmo_Bedna2"]

_loopArray = _nonCrashingThatRetainPositionZ
_i = 0
_instance = objNull

#loop
?!(isNull _instance): player sideChat format ["Removing instance ""%1""...", _instance], deleteVehicle _instance

_className = _loopArray select _i
player sideChat format ["Trying to create an instance of ""%1""...", _className]

~1

_instance = _className createVehicle _position
player sideChat format ["  Instance created, trying to call getPos.", _instance]

~1

player sideChat format ["  %1", getPos _instance]

_i = _i + 1

?_i >= count _loopArray: exit
goto "loop"

 

 

  • Like 2

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×