2022-01-23 08:54:49 +00:00
|
|
|
/*
|
|
|
|
** actorinfo.cpp
|
|
|
|
** Keeps track of available actors and their states
|
|
|
|
**
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
** Copyright 1998-2006 Randy Heit
|
|
|
|
** Copyright 2005-2022 Christoph Oelckers
|
|
|
|
** All rights reserved.
|
|
|
|
**
|
|
|
|
** Redistribution and use in source and binary forms, with or without
|
|
|
|
** modification, are permitted provided that the following conditions
|
|
|
|
** are met:
|
|
|
|
**
|
|
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer.
|
|
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
|
|
** documentation and/or other materials provided with the distribution.
|
|
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
|
|
** derived from this software without specific prior written permission.
|
|
|
|
**
|
|
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "actorinfo.h"
|
|
|
|
#include "c_dispatch.h"
|
|
|
|
#include "d_net.h"
|
|
|
|
#include "v_text.h"
|
|
|
|
|
|
|
|
#include "gi.h"
|
|
|
|
#include "coreactor.h"
|
|
|
|
#include "stats.h"
|
|
|
|
#include "types.h"
|
|
|
|
#include "filesystem.h"
|
|
|
|
#include "texturemanager.h"
|
|
|
|
|
|
|
|
extern void LoadActors ();
|
|
|
|
|
|
|
|
cycle_t ActionCycles;
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// special type for the native ActorInfo. This allows to let this struct
|
|
|
|
// be handled by the generic object constructors for the VM.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
class PActorInfo : public PCompoundType
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PActorInfo()
|
|
|
|
:PCompoundType(sizeof(FActorInfo), alignof(FActorInfo))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) override
|
|
|
|
{
|
|
|
|
if (base != nullptr) new((uint8_t *)base + offset) FActorInfo;
|
|
|
|
if (special != nullptr)
|
|
|
|
{
|
|
|
|
special->Push(std::make_pair(this, offset));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InitializeValue(void *addr, const void *def) const override
|
|
|
|
{
|
2022-11-14 17:15:58 +00:00
|
|
|
if (def == nullptr)
|
|
|
|
{
|
|
|
|
new(addr) FActorInfo;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new(addr) FActorInfo(*(const FActorInfo*)def);
|
|
|
|
}
|
2022-01-23 08:54:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DestroyValue(void *addr) const override
|
|
|
|
{
|
|
|
|
FActorInfo *self = (FActorInfo*)addr;
|
|
|
|
self->~FActorInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
void AddActorInfo(PClass *cls)
|
|
|
|
{
|
|
|
|
auto type = new PActorInfo;
|
|
|
|
TypeTable.AddType(type, NAME_Actor);
|
|
|
|
cls->AddField("*", type, VARF_Meta);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// PClassActor :: StaticInit STATIC
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void PClassActor::StaticInit()
|
|
|
|
{
|
|
|
|
for (auto cls : AllClasses)
|
|
|
|
{
|
|
|
|
if (cls->IsDescendantOf(RUNTIME_CLASS(DCoreActor)))
|
|
|
|
{
|
|
|
|
AllActorClasses.Push(static_cast<PClassActor*>(cls));
|
2022-11-19 09:58:35 +00:00
|
|
|
static_cast<PClassActor*>(cls)->ActorInfo()->ResolveTextures(cls->TypeName.GetChars(), GetDefaultByType(cls));
|
2022-01-23 08:54:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// PClassActor :: SetReplacement
|
|
|
|
//
|
|
|
|
// Sets as a replacement class for another class.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
bool PClassActor::SetReplacement(FName replaceName)
|
|
|
|
{
|
|
|
|
// Check for "replaces"
|
|
|
|
if (replaceName != NAME_None)
|
|
|
|
{
|
|
|
|
// Get actor name
|
|
|
|
PClassActor *replacee = PClass::FindActor(replaceName);
|
|
|
|
|
|
|
|
if (replacee == nullptr)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (replacee != nullptr)
|
|
|
|
{
|
|
|
|
replacee->ActorInfo()->Replacement = this;
|
|
|
|
ActorInfo()->Replacee = replacee;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// PClassActor :: InitializeNativeDefaults
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void PClassActor::InitializeDefaults()
|
|
|
|
{
|
|
|
|
if (IsDescendantOf(RUNTIME_CLASS(DCoreActor)))
|
|
|
|
{
|
|
|
|
assert(Defaults == nullptr);
|
|
|
|
Defaults = (uint8_t*)M_Malloc(Size);
|
|
|
|
|
|
|
|
ConstructNative(Defaults);
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PClass::InitializeDefaults();
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// PClassActor :: GetReplacement
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
PClassActor *PClassActor::GetReplacement()
|
|
|
|
{
|
|
|
|
PClassActor *Replacement = ActorInfo()->Replacement;
|
|
|
|
if (Replacement == nullptr) return this;
|
|
|
|
return Replacement;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// PClassActor :: GetReplacee
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
PClassActor *PClassActor::GetReplacee()
|
|
|
|
{
|
|
|
|
PClassActor *Replacee = ActorInfo()->Replacee;
|
|
|
|
if (Replacee == nullptr) return this;
|
|
|
|
return Replacee;
|
|
|
|
}
|
|
|
|
|
2022-01-16 23:51:40 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// This can only be done after all data has been set up.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2022-11-19 09:58:35 +00:00
|
|
|
void FActorInfo::ResolveTextures(const char* clsname, DCoreActor* defaults)
|
2022-01-16 23:51:40 +00:00
|
|
|
{
|
|
|
|
SpriteSet.Resize(SpriteSetNames.Size());
|
|
|
|
for (unsigned i = 0; i < SpriteSet.Size(); i++)
|
|
|
|
{
|
|
|
|
SpriteSet[i] = TileFiles.tileForName(SpriteSetNames[i]);
|
2022-11-20 08:35:59 +00:00
|
|
|
// This will print some noise in RR. Should later be restricted to user content.
|
|
|
|
#ifdef _DEBUG
|
|
|
|
if (SpriteSet[i] == -1) Printf(TEXTCOLOR_RED "Unknown texture '%s' in sprite set for class %s\n", SpriteSetNames[i].GetChars(), clsname);
|
|
|
|
#endif
|
2022-01-16 23:51:40 +00:00
|
|
|
}
|
2022-11-19 11:54:50 +00:00
|
|
|
if (SpriteSet.Size() > 0)
|
|
|
|
{
|
|
|
|
if (defaults->spritesetindex < 0 || defaults->spritesetindex >= (int)SpriteSet.Size()) defaults->spritesetindex = 0;
|
|
|
|
defaults->spr.picnum = SpriteSet[defaults->spritesetindex]; // Unless picnum is specified it will be set to the given image of the sprite set.
|
|
|
|
}
|
2022-01-16 23:51:40 +00:00
|
|
|
if (PicName.IsNotEmpty())
|
|
|
|
{
|
2022-11-19 09:58:35 +00:00
|
|
|
defaults->spr.picnum = TileFiles.tileForName(PicName);
|
2022-11-20 08:35:59 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
if (defaults->spr.picnum == -1) Printf(TEXTCOLOR_RED "Unknown texture '%s' in pic for class %s\n", PicName.GetChars(), clsname);
|
|
|
|
#endif
|
2022-01-16 23:51:40 +00:00
|
|
|
}
|
|
|
|
SpriteSetNames.Reset();
|
|
|
|
PicName = "";
|
|
|
|
}
|
|
|
|
|