Exemplo n.º 1
0
// Create a new class based on an existing class
PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
{
	assert (size >= Size);
	PClass *type;
	bool notnew;

	const PClass *existclass = FindClass(name);

	// This is a placeholder so fill it in
	if (existclass != NULL && existclass->Size == (unsigned)-1)
	{
		type = const_cast<PClass*>(existclass);
		if (!IsDescendantOf(type->ParentClass))
		{
			I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars());
		}
		DPrintf("Defining placeholder class %s\n", name.GetChars());
		notnew = true;
	}
	else
	{
		type = new PClass;
		notnew = false;
	}

	type->TypeName = name;
	type->ParentClass = this;
	type->Size = size;
	type->Pointers = NULL;
	type->ConstructNative = ConstructNative;
	if (!notnew)
	{
		type->ClassIndex = m_Types.Push (type);
	}
	type->Meta = Meta;

	// Set up default instance of the new class.
	type->Defaults = new BYTE[size];
	memcpy (type->Defaults, Defaults, Size);
	if (size > Size)
	{
		memset (type->Defaults + Size, 0, size - Size);
	}

	type->FlatPointers = NULL;
	type->bRuntimeClass = true;
	type->ActorInfo = NULL;
	type->Symbols.SetParentTable (&this->Symbols);
	if (!notnew) type->InsertIntoHash();

	// If this class has an actor info, then any classes derived from it
	// also need an actor info.
	if (this->ActorInfo != NULL)
	{
		FActorInfo *info = type->ActorInfo = new FActorInfo;
		info->Class = type;
		info->GameFilter = GAME_Any;
		info->SpawnID = 0;
		info->DoomEdNum = -1;
		info->OwnedStates = NULL;
		info->NumOwnedStates = 0;
		info->Replacement = NULL;
		info->Replacee = NULL;
		info->StateList = NULL;
		info->DamageFactors = NULL;
		info->PainChances = NULL;
		m_RuntimeActors.Push (type);
	}
	return type;
}
Exemplo n.º 2
0
void LoadActors()
{
	cycle_t timer;

	timer.Reset(); timer.Clock();
	FScriptPosition::ResetErrorCounter();

	InitThingdef();
	FScriptPosition::StrictErrors = true;
	ParseScripts();

	FScriptPosition::StrictErrors = false;
	ParseAllDecorate();

	FunctionBuildList.Build();

	if (FScriptPosition::ErrorCounter > 0)
	{
		I_Error("%d errors while parsing DECORATE scripts", FScriptPosition::ErrorCounter);
	}
	FScriptPosition::ResetErrorCounter();

	for (int i = PClassActor::AllActorClasses.Size() - 1; i >= 0; i--)
	{
		auto ti = PClassActor::AllActorClasses[i];
		if (ti->Size == TentativeClass)
		{
			if (ti->ObjectFlags & OF_Transient)
			{
				Printf(TEXTCOLOR_ORANGE "Class %s referenced but not defined\n", ti->TypeName.GetChars());
				FScriptPosition::WarnCounter++;
				DObject::StaticPointerSubstitution(ti, nullptr);
				PClassActor::AllActorClasses.Delete(i);
			}
			else
			{
				Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars());
				FScriptPosition::ErrorCounter++;
			}
			continue;
		}

		if (GetDefaultByType(ti) == nullptr)
		{
			Printf(TEXTCOLOR_RED "No ActorInfo defined for class '%s'\n", ti->TypeName.GetChars());
			FScriptPosition::ErrorCounter++;
			continue;
		}


		CheckStates(ti);

		if (ti->bDecorateClass && ti->IsDescendantOf(RUNTIME_CLASS(AStateProvider)))
		{
			// either a DECORATE based weapon or CustomInventory. 
			// These are subject to relaxed rules for user variables in states.
			// Although there is a runtime check for bogus states, let's do a quick analysis if any of the known entry points
			// hits an unsafe state. If we can find something here it can be handled wuth a compile error rather than a runtime error.
			CheckForUnsafeStates(ti);
		}

	}
	if (FScriptPosition::ErrorCounter > 0)
	{
		I_Error("%d errors during actor postprocessing", FScriptPosition::ErrorCounter);
	}

	timer.Unclock();
	if (!batchrun) Printf("script parsing took %.2f ms\n", timer.TimeMS());

	// Since these are defined in DECORATE now the table has to be initialized here.
	for (int i = 0; i < 31; i++)
	{
		char fmt[20];
		mysnprintf(fmt, countof(fmt), "QuestItem%d", i + 1);
		QuestItemClasses[i] = PClass::FindActor(fmt);
	}
	StateSourceLines.Clear();
}
Exemplo n.º 3
0
void PClass::InitializeDefaults()
{
	if (IsDescendantOf(RUNTIME_CLASS(AActor)))
	{
		assert(Defaults == nullptr);
		Defaults = (uint8_t *)M_Malloc(Size);

		// run the constructor on the defaults to set the vtbl pointer which is needed to run class-aware functions on them.
		// Temporarily setting bSerialOverride prevents linking into the thinker chains.
		auto s = DThinker::bSerialOverride;
		DThinker::bSerialOverride = true;
		ConstructNative(Defaults);
		DThinker::bSerialOverride = s;
		// We must unlink the defaults from the class list because it's just a static block of data to the engine.
		DObject *optr = (DObject*)Defaults;
		GC::Root = optr->ObjNext;
		optr->ObjNext = nullptr;
		optr->SetClass(this);

		// Copy the defaults from the parent but leave the DObject part alone because it contains important data.
		if (ParentClass->Defaults != nullptr)
		{
			memcpy(Defaults + sizeof(DObject), ParentClass->Defaults + sizeof(DObject), ParentClass->Size - sizeof(DObject));
			if (Size > ParentClass->Size)
			{
				memset(Defaults + ParentClass->Size, 0, Size - ParentClass->Size);
			}
		}
		else
		{
			memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject));
		}

		assert(MetaSize >= ParentClass->MetaSize);
		if (MetaSize != 0)
		{
			Meta = (uint8_t*)M_Malloc(MetaSize);

			// Copy the defaults from the parent but leave the DObject part alone because it contains important data.
			if (ParentClass->Meta != nullptr)
			{
				memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize);
				if (MetaSize > ParentClass->MetaSize)
				{
					memset(Meta + ParentClass->MetaSize, 0, MetaSize - ParentClass->MetaSize);
				}
			}
			else
			{
				memset(Meta, 0, MetaSize);
			}

			if (MetaSize > 0) memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize);
			else memset(Meta, 0, MetaSize);
		}
	}

	if (VMType != nullptr)	// purely internal classes have no symbol table
	{
		if (bRuntimeClass)
		{
			// Copy parent values from the parent defaults.
			assert(ParentClass != nullptr);
			if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults, &PClass::SpecialInits);
			for (const PField *field : Fields)
			{
				if (!(field->Flags & VARF_Native) && !(field->Flags & VARF_Meta))
				{
					field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits);
				}
			}
		}
		if (Meta != nullptr) ParentClass->InitializeSpecials(Meta, ParentClass->Meta, &PClass::MetaInits);
		for (const PField *field : Fields)
		{
			if (!(field->Flags & VARF_Native) && (field->Flags & VARF_Meta))
			{
				field->Type->SetDefaultValue(Meta, unsigned(field->Offset), &MetaInits);
			}
		}
	}
}