Shipwright/ZAPDTR/ZAPD/ZActorList.cpp

195 lines
5.0 KiB
C++

#include "ZActorList.h"
#include "Globals.h"
#include "Utils/BitConverter.h"
#include "WarningHandler.h"
#include "ZFile.h"
#include "ZRoom/ZNames.h"
REGISTER_ZFILENODE(ActorList, ZActorList);
ZActorList::ZActorList(ZFile* nParent) : ZResource(nParent)
{
RegisterRequiredAttribute("Count");
}
void ZActorList::ExtractFromBinary(uint32_t nRawDataIndex, uint8_t nNumActors)
{
rawDataIndex = nRawDataIndex;
numActors = nNumActors;
// Don't parse raw data of external files
if (parent->GetMode() == ZFileMode::ExternalFile)
return;
ParseRawData();
}
void ZActorList::ParseXML(tinyxml2::XMLElement* reader)
{
ZResource::ParseXML(reader);
numActors = StringHelper::StrToL(registeredAttributes.at("Count").value);
if (numActors < 1)
{
HANDLE_ERROR_RESOURCE(
WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
StringHelper::Sprintf("invalid value '%d' found for 'NumPaths' attribute", numActors),
"Should be at least '1'");
}
}
void ZActorList::ParseRawData()
{
ZResource::ParseRawData();
offset_t currentPtr = rawDataIndex;
size_t largestlength = 0;
for (size_t i = 0; i < numActors; i++)
{
ActorSpawnEntry entry(parent->GetRawData(), currentPtr);
currentPtr += entry.GetRawDataSize();
actors.push_back(entry);
size_t actorNameLength = ZNames::GetActorName(entry.GetActorId()).size();
if (actorNameLength > largestlength)
largestlength = actorNameLength;
}
for (auto& entry : actors)
{
entry.SetLargestActorName(largestlength);
}
}
Declaration* ZActorList::DeclareVar(const std::string& prefix, const std::string& bodyStr)
{
std::string auxName = name;
if (name == "")
auxName = GetDefaultName(prefix);
Declaration* decl =
parent->AddDeclarationArray(rawDataIndex, GetDeclarationAlignment(), GetRawDataSize(),
GetSourceTypeName(), name, GetActorListArraySize(), bodyStr);
decl->staticConf = staticConf;
return decl;
}
std::string ZActorList::GetBodySourceCode() const
{
std::string declaration;
size_t index = 0;
for (auto& entry : actors)
{
declaration += StringHelper::Sprintf("\t{ %s },", entry.GetBodySourceCode().c_str());
if (index < actors.size() - 1)
declaration += "\n";
index++;
}
return declaration;
}
std::string ZActorList::GetSourceTypeName() const
{
return actors.front().GetSourceTypeName();
}
ZResourceType ZActorList::GetResourceType() const
{
return ZResourceType::ActorList;
}
size_t ZActorList::GetRawDataSize() const
{
return actors.size() * actors.front().GetRawDataSize();
}
size_t ZActorList::GetActorListArraySize() const
{
size_t actorCount = 0;
// Doing an else-if here so we only do the loop when the game is SW97.
// Actor 0x22 is removed from SW97, so we need to ensure that we don't increment the actor count
// for it.
if (Globals::Instance->game == ZGame::OOT_SW97)
{
actorCount = 0;
for (const auto& entry : actors)
if (entry.GetActorId() != 0x22)
actorCount++;
}
else
{
actorCount = actors.size();
}
return actorCount;
}
/* ActorSpawnEntry */
ActorSpawnEntry::ActorSpawnEntry(const std::vector<uint8_t>& rawData, uint32_t rawDataIndex)
{
actorNum = BitConverter::ToInt16BE(rawData, rawDataIndex + 0);
posX = BitConverter::ToInt16BE(rawData, rawDataIndex + 2);
posY = BitConverter::ToInt16BE(rawData, rawDataIndex + 4);
posZ = BitConverter::ToInt16BE(rawData, rawDataIndex + 6);
rotX = BitConverter::ToUInt16BE(rawData, rawDataIndex + 8);
rotY = BitConverter::ToUInt16BE(rawData, rawDataIndex + 10);
rotZ = BitConverter::ToUInt16BE(rawData, rawDataIndex + 12);
params = BitConverter::ToInt16BE(rawData, rawDataIndex + 14);
}
std::string ActorSpawnEntry::GetBodySourceCode() const
{
std::string body;
std::string actorNameFmt = StringHelper::Sprintf("%%-%zus ", largestActorName + 1);
body =
StringHelper::Sprintf(actorNameFmt.c_str(), (ZNames::GetActorName(actorNum) + ",").c_str());
body += StringHelper::Sprintf("{ %6i, %6i, %6i }, ", posX, posY, posZ);
if (Globals::Instance->game == ZGame::MM_RETAIL)
body += StringHelper::Sprintf("{ SPAWN_ROT_FLAGS(%#5hX, 0x%04X)"
", SPAWN_ROT_FLAGS(%#5hX, 0x%04X)"
", SPAWN_ROT_FLAGS(%#5hX, 0x%04X) }, ",
(rotX >> 7) & 0b111111111, rotX & 0b1111111,
(rotY >> 7) & 0b111111111, rotY & 0b1111111,
(rotZ >> 7) & 0b111111111, rotZ & 0b1111111);
else
body += StringHelper::Sprintf("{ %#6hX, %#6hX, %#6hX }, ", rotX, rotY, rotZ);
body += StringHelper::Sprintf("0x%04X", params);
return body;
}
std::string ActorSpawnEntry::GetSourceTypeName() const
{
return "ActorEntry";
}
size_t ActorSpawnEntry::GetRawDataSize() const
{
return 16;
}
uint16_t ActorSpawnEntry::GetActorId() const
{
return actorNum;
}
void ActorSpawnEntry::SetLargestActorName(size_t nameSize)
{
largestActorName = nameSize;
}