forked from teamnwah/openmw-tes3coop
		
	
		
			
				
	
	
		
			159 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			159 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "loaddial.hpp"
 | 
						|
 | 
						|
#include <iostream>
 | 
						|
 | 
						|
#include "esmreader.hpp"
 | 
						|
#include "esmwriter.hpp"
 | 
						|
#include "defs.hpp"
 | 
						|
 | 
						|
namespace ESM
 | 
						|
{
 | 
						|
    unsigned int Dialogue::sRecordId = REC_DIAL;
 | 
						|
 | 
						|
    void Dialogue::load(ESMReader &esm, bool &isDeleted)
 | 
						|
    {
 | 
						|
        loadId(esm);
 | 
						|
        loadData(esm, isDeleted);
 | 
						|
    }
 | 
						|
 | 
						|
    void Dialogue::loadId(ESMReader &esm)
 | 
						|
    {
 | 
						|
        mId = esm.getHNString("NAME");
 | 
						|
    }
 | 
						|
 | 
						|
    void Dialogue::loadData(ESMReader &esm, bool &isDeleted)
 | 
						|
    {
 | 
						|
        isDeleted = false;
 | 
						|
 | 
						|
        while (esm.hasMoreSubs())
 | 
						|
        {
 | 
						|
            esm.getSubName();
 | 
						|
            switch (esm.retSubName().val)
 | 
						|
            {
 | 
						|
                case ESM::FourCC<'D','A','T','A'>::value:
 | 
						|
                {
 | 
						|
                    esm.getSubHeader();
 | 
						|
                    int size = esm.getSubSize();
 | 
						|
                    if (size == 1)
 | 
						|
                    {
 | 
						|
                        esm.getT(mType);
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        esm.skip(size);
 | 
						|
                    }
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                case ESM::SREC_DELE:
 | 
						|
                    esm.skipHSub();
 | 
						|
                    mType = Unknown;
 | 
						|
                    isDeleted = true;
 | 
						|
                    break;
 | 
						|
                default:
 | 
						|
                    esm.fail("Unknown subrecord");
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void Dialogue::save(ESMWriter &esm, bool isDeleted) const
 | 
						|
    {
 | 
						|
        esm.writeHNCString("NAME", mId);
 | 
						|
        if (isDeleted)
 | 
						|
        {
 | 
						|
            esm.writeHNCString("DELE", "");
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            esm.writeHNT("DATA", mType);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void Dialogue::blank()
 | 
						|
    {
 | 
						|
        mInfo.clear();
 | 
						|
    }
 | 
						|
 | 
						|
    void Dialogue::readInfo(ESMReader &esm, bool merge)
 | 
						|
    {
 | 
						|
        ESM::DialInfo info;
 | 
						|
        info.loadId(esm);
 | 
						|
 | 
						|
        bool isDeleted = false;
 | 
						|
        if (!merge || mInfo.empty())
 | 
						|
        {
 | 
						|
            info.loadData(esm, isDeleted);
 | 
						|
            mLookup[info.mId] = std::make_pair(mInfo.insert(mInfo.end(), info), isDeleted);
 | 
						|
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        InfoContainer::iterator it = mInfo.end();
 | 
						|
 | 
						|
        LookupMap::iterator lookup;
 | 
						|
        lookup = mLookup.find(info.mId);
 | 
						|
 | 
						|
        if (lookup != mLookup.end())
 | 
						|
        {
 | 
						|
            it = lookup->second.first;
 | 
						|
 | 
						|
            // Merge with existing record. Only the subrecords that are present in
 | 
						|
            // the new record will be overwritten.
 | 
						|
            it->loadData(esm, isDeleted);
 | 
						|
            info = *it;
 | 
						|
 | 
						|
            // Since the record merging may have changed the next/prev linked list connection, we need to re-insert the record
 | 
						|
            mInfo.erase(it);
 | 
						|
            mLookup.erase(lookup);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            info.loadData(esm, isDeleted);
 | 
						|
        }
 | 
						|
 | 
						|
        if (info.mNext.empty())
 | 
						|
        {
 | 
						|
            mLookup[info.mId] = std::make_pair(mInfo.insert(mInfo.end(), info), isDeleted);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        if (info.mPrev.empty())
 | 
						|
        {
 | 
						|
            mLookup[info.mId] = std::make_pair(mInfo.insert(mInfo.begin(), info), isDeleted);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        lookup = mLookup.find(info.mPrev);
 | 
						|
        if (lookup != mLookup.end())
 | 
						|
        {
 | 
						|
            it = lookup->second.first;
 | 
						|
 | 
						|
            mLookup[info.mId] = std::make_pair(mInfo.insert(++it, info), isDeleted);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        lookup = mLookup.find(info.mNext);
 | 
						|
        if (lookup != mLookup.end())
 | 
						|
        {
 | 
						|
            it = lookup->second.first;
 | 
						|
 | 
						|
            mLookup[info.mId] = std::make_pair(mInfo.insert(it, info), isDeleted);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        std::cerr << "Failed to insert info " << info.mId << std::endl;
 | 
						|
    }
 | 
						|
 | 
						|
    void Dialogue::clearDeletedInfos()
 | 
						|
    {
 | 
						|
        LookupMap::const_iterator current = mLookup.begin();
 | 
						|
        LookupMap::const_iterator end = mLookup.end();
 | 
						|
        for (; current != end; ++current)
 | 
						|
        {
 | 
						|
            if (current->second.second)
 | 
						|
            {
 | 
						|
                mInfo.erase(current->second.first);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        mLookup.clear();
 | 
						|
    }
 | 
						|
}
 |