Page MenuHomeFeedback Tracker

Handling of casts, error in CalculateVisibilityForAI
Assigned, UrgentPublic

Description

Hello. This error has been happening quite a bit for a while, we are getting client logs hogged with this error

NULL pointer to instance
Class:      'SurvivorBase'
Entity id:2951224

Function: 'CalculateVisibilityForAI'
Stack trace:
scripts/4_World/entities\manbase\playerbase.c:4317
scripts/4_World/entities\manbase\playerbase.c:890
MuchStuffPack/MSP_Clothing_Data/scripts/4_World/playerbase.c:5
WindstrideClothing/scripts/4_World/playerbase.c:5
WillowGlade/WG_MedicalAttention/scripts/4_World/entities\manbase\playerbase.c:714

In the modded playerbase, each line points to super.EEItemAttached(item, slot_name);
Problem is when casting the attachment to ClothingBase it's failing. There's no handling if the cast fails which is causing the error. Argument could be that maybe we do need to raise an error if a modded item is setup wrong but i'd rather not have 1.5gb worth of errors in clients logs. From tests it seems it's failing to cast items that are defined as "Clothing_Base" in config, rather than inheriting from "Clothing". Maybe casts should be on Clothing_Base instead? Several possibilities here to sort this out.

Vanilla code:

	void CalculateVisibilityForAI()
	{
		const int VISIBILITY_SLOTS_COUNT = 10;

		int attcount = GetInventory().AttachmentCount();
		float sumVisibility = 0;
		float countVisibility = 0;
		float visibilityMean = 0;

		if (attcount > 0)
		{
			for (int att = 0; att < attcount; att++)
			{
				EntityAI attachment = GetInventory().GetAttachmentFromIndex(att);
				if ( attachment.IsClothing() )
				{
					ClothingBase clothing;
					Class.CastTo(clothing, attachment);
					sumVisibility += clothing.GetItemVisibility();
					countVisibility++;
				}
			}

			visibilityMean = (sumVisibility + (VISIBILITY_SLOTS_COUNT - countVisibility)) / VISIBILITY_SLOTS_COUNT;
			SetVisibilityCoef(visibilityMean);
		}
		else
		{
			visibilityMean = 1;
			SetVisibilityCoef(visibilityMean);
		}
	}

How it should be maybe:

	void CalculateVisibilityForAI()
	{
		const int VISIBILITY_SLOTS_COUNT = 10;

		int attcount = GetInventory().AttachmentCount();
		float sumVisibility = 0;
		float countVisibility = 0;
		float visibilityMean = 0;

		if (attcount > 0)
		{
			for (int att = 0; att < attcount; att++)
			{
				EntityAI attachment = GetInventory().GetAttachmentFromIndex(att);
				if ( attachment.IsClothing() )
				{
					ClothingBase clothing;
                    			if(!Class.CastTo(clothing, attachment))
                        			continue;
					sumVisibility += clothing.GetItemVisibility();
					countVisibility++;
				}
			}

			visibilityMean = (sumVisibility + (VISIBILITY_SLOTS_COUNT - countVisibility)) / VISIBILITY_SLOTS_COUNT;
			SetVisibilityCoef(visibilityMean);
		}
		else
		{
			visibilityMean = 1;
			SetVisibilityCoef(visibilityMean);
		}
	}
	void CalculateVisibilityForAI()
	{
		const int VISIBILITY_SLOTS_COUNT = 10;

		int attcount = GetInventory().AttachmentCount();
		float sumVisibility = 0;
		float countVisibility = 0;
		float visibilityMean = 0;

		if (attcount > 0)
		{
			for (int att = 0; att < attcount; att++)
			{
				EntityAI attachment = GetInventory().GetAttachmentFromIndex(att);
				if ( attachment.IsClothing() )
				{
					Clothing_Base clothing; //Using clothing_base as cast instead?
                    			if(!Class.CastTo(clothing, attachment))
                        			continue;
					sumVisibility += clothing.GetItemVisibility();
					countVisibility++;
				}
			}

			visibilityMean = (sumVisibility + (VISIBILITY_SLOTS_COUNT - countVisibility)) / VISIBILITY_SLOTS_COUNT;
			SetVisibilityCoef(visibilityMean);
		}
		else
		{
			visibilityMean = 1;
			SetVisibilityCoef(visibilityMean);
		}
	}

Details

Severity
Tweak
Resolution
Open
Reproducibility
Sometimes
Operating System
Windows 10
Category
General

Event Timeline

Geez changed the task status from New to Assigned.Jul 22 2021, 3:31 PM
This comment was removed by BIS_fnc_KK.
tjensen added a subscriber: tjensen.Mar 6 2022, 2:14 AM

Hopefully this gets addressed but, in the meanwhile, I've created this script snippet to identify modded clothing items that may generate the error:

int count = GetGame().ConfigGetChildrenCount("CfgVehicles");
string child;

PrintFormat("Checking %1 types", count);
for (int i = 0; i < count; ++i)
{
    if (!GetGame().ConfigGetChildName("CfgVehicles", i, child))
    {
        continue;
    }

    if (GetGame().ConfigGetInt(string.Format("CfgVehicles %1 scope", child)) != 2)
    {
        continue;
    }

    Object obj = GetGame().CreateObject(child, "0 0 0");
    if (obj && obj.IsClothing() && Clothing.Cast(obj) == null)
    {
        PrintFormat("Bad clothing type: %1", child);
    }
    GetGame().ObjectDelete(obj);
}
Print("Done checking types");

Hopefully this gets addressed but, in the meanwhile, I've created this script snippet to identify modded clothing items that may generate the error:

int count = GetGame().ConfigGetChildrenCount("CfgVehicles");
string child;
 
PrintFormat("Checking %1 types", count);
for (int i = 0; i < count; ++i)
{
    if (!GetGame().ConfigGetChildName("CfgVehicles", i, child))
    {
        continue;
    }
 
    if (GetGame().ConfigGetInt(string.Format("CfgVehicles %1 scope", child)) != 2)
    {
        continue;
    }
 
    Object obj = GetGame().CreateObject(child, "0 0 0");
    if (obj && obj.IsClothing() && Clothing.Cast(obj) == null)
    {
        PrintFormat("Bad clothing type: %1", child);
    }
    GetGame().ObjectDelete(obj);
}
Print("Done checking types");

Hello, how do I go about using this script to identify the clothing?

this is not vanilla issue, and never was.
u have clothes on itembase somewhere, with missing configs.