Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MQO reading #251

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ set(PRP_MOD_SOURCES
PRP/Modifier/plAliasModifier.cpp
PRP/Modifier/plAnimEventModifier.cpp
PRP/Modifier/plAxisAnimModifier.cpp
PRP/Modifier/plCloneSpawnModifier.cpp
PRP/Modifier/plExcludeRegionModifier.cpp
PRP/Modifier/plFollowMod.cpp
PRP/Modifier/plGameMarkerModifier.cpp
Expand All @@ -417,6 +418,7 @@ set(PRP_MOD_HEADERS
PRP/Modifier/plAliasModifier.h
PRP/Modifier/plAnimEventModifier.h
PRP/Modifier/plAxisAnimModifier.h
PRP/Modifier/plCloneSpawnModifier.h
PRP/Modifier/plExcludeRegionModifier.h
PRP/Modifier/plFollowMod.h
PRP/Modifier/plGameMarkerModifier.h
Expand Down
16 changes: 16 additions & 0 deletions core/PRP/Avatar/plAGAnim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ void plAGAnim::read(hsStream* S, plResManager* mgr)
fStart = S->readFloat();
fEnd = S->readFloat();

// MQO data
if (S->getVer().isMoul() && pdUnifiedTypeMap::CurrentVersion(this->ClassIndex()) >= 5) {
fUnknownMQO1 = S->readFloat();
fUnknownMQO2 = S->readFloat();
}

clearApplicators();
fApps.resize(S->readInt());
for (size_t i=0; i<fApps.size(); i++) {
Expand All @@ -52,6 +58,12 @@ void plAGAnim::write(hsStream* S, plResManager* mgr)
S->writeFloat(fStart);
S->writeFloat(fEnd);

// MQO data
if (S->getVer().isMoul() && pdUnifiedTypeMap::CurrentVersion(this->ClassIndex()) >= 5) {
S->writeFloat(fUnknownMQO1);
S->writeFloat(fUnknownMQO2);
}

S->writeInt(fApps.size());
for (size_t i=0; i<fApps.size(); i++) {
mgr->WriteCreatable(S, fApps[i]);
Expand All @@ -70,6 +82,8 @@ void plAGAnim::IPrcWrite(pfPrcHelper* prc)
prc->writeParam("Name", fName);
prc->writeParam("Start", fStart);
prc->writeParam("End", fEnd);
prc->writeParam("UnknownMQO1", fUnknownMQO1);
prc->writeParam("UnknownMQO2", fUnknownMQO2);
prc->writeParam("EoaFlag", fEoaFlag);
prc->endTag(true);

Expand All @@ -93,6 +107,8 @@ void plAGAnim::IPrcParse(const pfPrcTag* tag, plResManager* mgr)
fName = tag->getParam("Name", "");
fStart = tag->getParam("Start", "0").to_float();
fEnd = tag->getParam("End", "0").to_float();
fUnknownMQO1 = tag->getParam("UnknownMQO1", "0").to_float();
fUnknownMQO2 = tag->getParam("UnknownMQO2", "0").to_float();
fEoaFlag = tag->getParam("EoaFlag", "0").to_uint();
} else if (tag->getName() == "Applicators") {
clearApplicators();
Expand Down
3 changes: 2 additions & 1 deletion core/PRP/Avatar/plAGAnim.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ class HSPLASMA_EXPORT plAGAnim : public plSynchedObject
protected:
std::vector<plAGApplicator*> fApps;
float fBlend, fStart, fEnd;
float fUnknownMQO1, fUnknownMQO2;
ST::string fName;
unsigned char fEoaFlag;

public:
plAGAnim() : fBlend(), fStart(), fEnd(), fEoaFlag() { }
plAGAnim() : fBlend(), fStart(), fEnd(), fUnknownMQO1(), fUnknownMQO2(), fEoaFlag() { }
~plAGAnim();

void read(hsStream* S, plResManager* mgr) HS_OVERRIDE;
Expand Down
5 changes: 4 additions & 1 deletion core/PRP/Avatar/plMultistageBehMod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ void plMultistageBehMod::read(hsStream* S, plResManager* mgr)

fFreezePhys = S->readBool();
fSmartSeek = S->readBool();
fReverseFBControlsOnRelease = S->readBool();

if (S->getVer() >= MAKE_VERSION(2, 0, 62, 12)) {
fReverseFBControlsOnRelease = S->readBool();
}

clearStages();
fStages.resize(S->readInt());
Expand Down
10 changes: 7 additions & 3 deletions core/PRP/KeyedObject/plLoadMask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@

void plLoadMask::read(hsStream* S)
{
unsigned char m = S->readByte();
fQuality[0] = (m >> 4) | 0xF0;
fQuality[1] = m | 0xF0;
if (S->getVer() < MAKE_VERSION(2, 0, 63, 0) && S->getVer().isValid()) {
S->readInt();
} else {
unsigned char m = S->readByte();
fQuality[0] = (m >> 4) | 0xF0;
fQuality[1] = m | 0xF0;
}
}

void plLoadMask::write(hsStream* S)
Expand Down
4 changes: 4 additions & 0 deletions core/PRP/KeyedObject/plUoid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ void plUoid::read(hsStream* S)
unsigned char contents = 0;
if (S->getVer() < MAKE_VERSION(2, 0, 63, 0) && S->getVer().isValid()) {
contents = kHasCloneIDs;

if (S->getVer() > MAKE_VERSION(2, 0, 62, 0)) {
contents |= kHasLoadMask;
}
} else {
contents = S->readByte();
}
Expand Down
15 changes: 15 additions & 0 deletions core/PRP/Message/plCameraMsg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ void plCameraMsg::read(hsStream* S, plResManager* mgr)
fNewCam = mgr->readKey(S);
fTriggerer = mgr->readKey(S);
fConfig.read(S);

if (S->getVer().isMqo()) {
fUnknownMQO.read(S);
}
}

void plCameraMsg::write(hsStream* S, plResManager* mgr)
Expand All @@ -166,6 +170,10 @@ void plCameraMsg::write(hsStream* S, plResManager* mgr)
mgr->writeKey(S, fNewCam);
mgr->writeKey(S, fTriggerer);
fConfig.write(S);

if (S->getVer().isMqo()) {
fUnknownMQO.write(S);
}
}

void plCameraMsg::IPrcWrite(pfPrcHelper* prc)
Expand All @@ -189,6 +197,10 @@ void plCameraMsg::IPrcWrite(pfPrcHelper* prc)
prc->closeTag();

fConfig.prcWrite(prc);

prc->writeSimpleTag("UnknownMQO");
fUnknownMQO.prcWrite(prc);
prc->closeTag();
}

void plCameraMsg::IPrcParse(const pfPrcTag* tag, plResManager* mgr)
Expand All @@ -207,6 +219,9 @@ void plCameraMsg::IPrcParse(const pfPrcTag* tag, plResManager* mgr)
fTriggerer = mgr->prcParseKey(tag->getFirstChild());
} else if (tag->getName() == "plCameraConfig") {
fConfig.prcParse(tag);
} else if (tag->getName() == "UnknownMQO") {
if (tag->hasChildren())
fUnknownMQO.prcParse(tag->getFirstChild());
} else {
plMessage::IPrcParse(tag, mgr);
}
Expand Down
1 change: 1 addition & 0 deletions core/PRP/Message/plCameraMsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class HSPLASMA_EXPORT plCameraMsg : public plMessage
plCameraConfig fConfig;
bool fActivated;
hsBitVector fCmd;
hsVector3 fUnknownMQO;

public:
plCameraMsg();
Expand Down
64 changes: 64 additions & 0 deletions core/PRP/Modifier/plCloneSpawnModifier.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* This file is part of HSPlasma.
*
* HSPlasma is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HSPlasma is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HSPlasma. If not, see <http://www.gnu.org/licenses/>.
*/

#include "plCloneSpawnModifier.h"

void plCloneSpawnModifier::read(hsStream* S, plResManager* mgr)
{
if (S->getVer().isMoul()) {
plSingleModifier::read(S, mgr);
fTemplateName = S->readSafeStr();
fUserData = S->readInt();
} else {
// This is bad, but also never used in earlier Plasma versions
fTemplateName = S->readSafeStr();
plSingleModifier::read(S, mgr);
}
}

void plCloneSpawnModifier::write(hsStream* S, plResManager* mgr)
{
if (S->getVer().isMoul()) {
plSingleModifier::write(S, mgr);
S->writeSafeStr(fTemplateName);
S->writeInt(fUserData);
} else {
// This is bad, but also never used in earlier Plasma versions
S->writeSafeStr(fTemplateName);
plSingleModifier::write(S, mgr);
}
}

void plCloneSpawnModifier::IPrcWrite(pfPrcHelper* prc)
{
plSingleModifier::IPrcWrite(prc);

prc->startTag("SpawnParams");
prc->writeParam("TemplateName", fTemplateName);
prc->writeParam("UserData", fUserData);
prc->endTag(true);
}

void plCloneSpawnModifier::IPrcParse(const pfPrcTag* tag, plResManager* mgr)
{
if (tag->getName() == "SpawnParams") {
fTemplateName = tag->getParam("TemplateName", "");
fUserData = tag->getParam("UserData", "0").to_uint();
} else {
plSingleModifier::IPrcParse(tag, mgr);
}
}

41 changes: 41 additions & 0 deletions core/PRP/Modifier/plCloneSpawnModifier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* This file is part of HSPlasma.
*
* HSPlasma is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HSPlasma is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HSPlasma. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _PLCLONESPAWNMODIFIER_H
#define _PLCLONESPAWNMODIFIER_H

#include "plModifier.h"

class HSPLASMA_EXPORT plCloneSpawnModifier : public plSingleModifier
{
CREATABLE(plCloneSpawnModifier, kCloneSpawnModifier, plSingleModifier)

protected:
ST::string fTemplateName;
uint32_t fUserData;

public:
plCloneSpawnModifier() : fUserData() { }

void read(hsStream* S, plResManager* mgr) HS_OVERRIDE;
void write(hsStream* S, plResManager* mgr) HS_OVERRIDE;

protected:
void IPrcWrite(pfPrcHelper* prc) HS_OVERRIDE;
void IPrcParse(const pfPrcTag* tag, plResManager* mgr) HS_OVERRIDE;
};

#endif
12 changes: 11 additions & 1 deletion core/PRP/Modifier/plOneShotMod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@ void plOneShotMod::read(hsStream* S, plResManager* mgr)
fReversable = S->readBool();
fSmartSeek = S->readBool();

if (S->getVer() > 0x02006304) { /*TODO: Verify! */
if (S->getVer() > MAKE_VERSION(2, 0, 63, 4)) {
fNoSeek = S->readBool();
}

if (S->getVer().isMoul() && pdUnifiedTypeMap::CurrentVersion(this->ClassIndex()) >= 3) {
fUnknownMQO = S->readBool();
}
}

void plOneShotMod::write(hsStream* S, plResManager* mgr)
Expand All @@ -41,6 +45,10 @@ void plOneShotMod::write(hsStream* S, plResManager* mgr)
S->writeBool(fReversable);
S->writeBool(fSmartSeek);
S->writeBool(fNoSeek);

if (S->getVer().isMoul() && pdUnifiedTypeMap::CurrentVersion(this->ClassIndex()) >= 3) {
S->writeBool(fUnknownMQO);
}
}

void plOneShotMod::IPrcWrite(pfPrcHelper* prc)
Expand All @@ -54,6 +62,7 @@ void plOneShotMod::IPrcWrite(pfPrcHelper* prc)
prc->writeParam("Reversable", fReversable);
prc->writeParam("SmartSeek", fSmartSeek);
prc->writeParam("NoSeek", fNoSeek);
prc->writeParam("UnknownMQO", fUnknownMQO);
prc->endTag(true);
}

Expand All @@ -66,6 +75,7 @@ void plOneShotMod::IPrcParse(const pfPrcTag* tag, plResManager* mgr)
fReversable = tag->getParam("Reversable", "false").to_bool();
fSmartSeek = tag->getParam("SmartSeek", "false").to_bool();
fNoSeek = tag->getParam("NoSeek", "true").to_bool();
fUnknownMQO = tag->getParam("UnknownMQO", "false").to_bool();
} else {
plMultiModifier::IPrcParse(tag, mgr);
}
Expand Down
4 changes: 2 additions & 2 deletions core/PRP/Modifier/plOneShotMod.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ class HSPLASMA_EXPORT plOneShotMod : public plMultiModifier

protected:
ST::string fAnimName;
bool fDrivable, fReversable, fSmartSeek, fNoSeek;
bool fDrivable, fReversable, fSmartSeek, fNoSeek, fUnknownMQO;
float fSeekDuration;

public:
plOneShotMod()
: fDrivable(), fReversable(), fSmartSeek(), fNoSeek(true),
fSeekDuration() { }
fUnknownMQO(), fSeekDuration() { }

void read(hsStream* S, plResManager* mgr) HS_OVERRIDE;
void write(hsStream* S, plResManager* mgr) HS_OVERRIDE;
Expand Down
4 changes: 4 additions & 0 deletions core/PRP/Physics/plGenericPhysical.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ void plGenericPhysical::read(hsStream* S, plResManager* mgr)
{
plSynchedObject::read(S, mgr);

if (S->getVer() < MAKE_VERSION(2, 0, 63, 0)) {
return;
}

if (S->getVer().isUniversal())
fInternalType = (PhysType)S->readInt();
else if (S->getVer().isNewPlasma())
Expand Down
19 changes: 19 additions & 0 deletions core/PRP/plPageInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,25 @@ void plPageInfo::read(hsStream* S)
pdUnifiedTypeMap::ClassVersion(type, S->getVer()), ver);
}
}

// We have a slight problem with MQO data, because it is effectively
// indistinguishable from MOUL data. Most classes correctly use the
// type map to indicate when they have been updated, with the exception
// of plMessages embedded within ResponderModifiers. We have no way of
// knowing when there is extra data to read in those messages, and
// failing to read it correctly will corrupt the stream and probably
// crash.
//
// Since there is a finite set of MQO files, we're going to hackily
// check what Age we're reading here and compare the Age name and
// sequence prefix against known MQO Ages, and then set our stream
// version to pvMqo (which isn't actually accurate, but we need *some*
// way to track this when reading)
if ((fAge == "Courtyard" && fLocation.getSeqPrefix() == 3)
|| (fAge == "Forest" && fLocation.getSeqPrefix() == 5)
|| (fAge == "PortalWell" && fLocation.getSeqPrefix() == 1)) {
S->setVer(PlasmaVer::pvMqo);
}
}

plDebug::Debug("* Loading: {} ({})\n"
Expand Down
4 changes: 4 additions & 0 deletions core/ResManager/pdUnifiedTypeMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2187,6 +2187,7 @@ short pdUnifiedTypeMap::PlasmaToMapped(short typeIdx, PlasmaVer ver)
case PlasmaVer::pvPots:
return fPotSP2MTable[typeIdx];
case PlasmaVer::pvMoul:
case PlasmaVer::pvMqo:
return fLiveP2MTable[typeIdx];
case PlasmaVer::pvEoa:
return fEoaP2MTable[typeIdx];
Expand Down Expand Up @@ -2214,6 +2215,7 @@ short pdUnifiedTypeMap::MappedToPlasma(short typeIdx, PlasmaVer ver)
case PlasmaVer::pvPots:
return fPotSM2PTable[typeIdx];
case PlasmaVer::pvMoul:
case PlasmaVer::pvMqo:
return fLiveM2PTable[typeIdx];
case PlasmaVer::pvEoa:
return fEoaM2PTable[typeIdx];
Expand All @@ -2233,6 +2235,7 @@ short pdUnifiedTypeMap::ClassVersion(short typeIdx, PlasmaVer ver)

switch (ver) {
case PlasmaVer::pvMoul:
case PlasmaVer::pvMqo:
return fLiveVerTable[PlasmaToMapped(typeIdx, ver)];
case PlasmaVer::pvEoa:
return fEoaVerTable[PlasmaToMapped(typeIdx, ver)];
Expand All @@ -2259,6 +2262,7 @@ void pdUnifiedTypeMap::SetCurrentVersionBase(PlasmaVer ver)

switch (ver) {
case PlasmaVer::pvMoul:
case PlasmaVer::pvMqo:
base = fLiveVerTable;
break;
case PlasmaVer::pvEoa:
Expand Down
Loading
Loading