forked from Mirrors/openclonk
273 lines
6.1 KiB
C++
273 lines
6.1 KiB
C++
/*
|
|
* OpenClonk, http://www.openclonk.org
|
|
*
|
|
* Copyright (c) 1998-2000, 2003 Matthes Bender
|
|
* Copyright (c) 2002, 2004-2005 Sven Eberhardt
|
|
* Copyright (c) 2002, 2008 Peter Wortmann
|
|
* Copyright (c) 2006, 2008-2009 Günther Brammer
|
|
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
|
|
*
|
|
* Portions might be copyrighted by other authors who have contributed
|
|
* to OpenClonk.
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
* See isc_license.txt for full license and disclaimer.
|
|
*
|
|
* "Clonk" is a registered trademark of Matthes Bender.
|
|
* See clonk_trademark_license.txt for full license.
|
|
*/
|
|
|
|
/* Dynamic list for crew member info */
|
|
|
|
#include <C4Include.h>
|
|
#include <C4ObjectInfoList.h>
|
|
|
|
#include <C4DefList.h>
|
|
#include <C4ObjectInfo.h>
|
|
#include <C4Components.h>
|
|
#include <C4Game.h>
|
|
#include <C4RankSystem.h>
|
|
#include <C4Config.h>
|
|
#include <C4GameObjects.h>
|
|
|
|
C4ObjectInfoList::C4ObjectInfoList()
|
|
{
|
|
Default();
|
|
}
|
|
|
|
C4ObjectInfoList::~C4ObjectInfoList()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void C4ObjectInfoList::Default()
|
|
{
|
|
First=NULL;
|
|
iNumCreated=0;
|
|
}
|
|
|
|
void C4ObjectInfoList::Clear()
|
|
{
|
|
C4ObjectInfo *next;
|
|
while (First)
|
|
{
|
|
next=First->Next;
|
|
delete First;
|
|
First=next;
|
|
}
|
|
}
|
|
|
|
int32_t C4ObjectInfoList::Load(C4Group &hGroup)
|
|
{
|
|
C4ObjectInfo *ninf;
|
|
int32_t infn=0;
|
|
char entryname[256+1];
|
|
|
|
// Search all oci files
|
|
hGroup.ResetSearch();
|
|
while (hGroup.FindNextEntry(C4CFN_ObjectInfoFiles,entryname))
|
|
if ((ninf=new C4ObjectInfo))
|
|
{
|
|
if (ninf->Load(hGroup,entryname)) { Add(ninf); infn++; }
|
|
else delete ninf;
|
|
}
|
|
|
|
// Search all c4o files
|
|
/*hGroup.ResetSearch();
|
|
while (hGroup.FindNextEntry("*.c4o",entryname))
|
|
if (ninf=new C4ObjectInfo)
|
|
if (ninf->Load(hGroup,entryname)) { Add(ninf); infn++; }
|
|
else delete ninf;*/
|
|
|
|
// Search subfolders
|
|
hGroup.ResetSearch();
|
|
while (hGroup.FindNextEntry("*", entryname))
|
|
{
|
|
C4Group ItemGroup;
|
|
if (ItemGroup.OpenAsChild(&hGroup, entryname))
|
|
Load(ItemGroup);
|
|
}
|
|
|
|
return infn;
|
|
}
|
|
|
|
bool C4ObjectInfoList::Add(C4ObjectInfo *pInfo)
|
|
{
|
|
if (!pInfo) return false;
|
|
pInfo->Next=First;
|
|
First=pInfo;
|
|
return true;
|
|
}
|
|
|
|
void C4ObjectInfoList::MakeValidName(char *sName)
|
|
{
|
|
char tstr[_MAX_PATH];
|
|
int32_t iname,namelen=SLen(sName);
|
|
for (iname=2; NameExists(sName); iname++)
|
|
{
|
|
sprintf(tstr," %d",iname);
|
|
SCopy(tstr,sName+Min<int32_t>(namelen,C4MaxName-SLen(tstr)));
|
|
}
|
|
}
|
|
|
|
bool C4ObjectInfoList::NameExists(const char *szName)
|
|
{
|
|
C4ObjectInfo *cinf;
|
|
for (cinf=First; cinf; cinf=cinf->Next)
|
|
if (SEqualNoCase(szName,cinf->Name))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
C4ObjectInfo* C4ObjectInfoList::GetIdle(C4ID c_id, C4DefList &rDefs)
|
|
{
|
|
C4Def *pDef;
|
|
C4ObjectInfo *pInfo;
|
|
C4ObjectInfo *pHiExp=NULL;
|
|
|
|
// Search list
|
|
for (pInfo=First; pInfo; pInfo=pInfo->Next)
|
|
// Valid only
|
|
if ((pDef = rDefs.ID2Def(pInfo->id)))
|
|
// Use standard crew or matching id
|
|
if ( (!c_id && !pDef->NativeCrew) || (pInfo->id==c_id) )
|
|
// Participating and not in action
|
|
if (pInfo->Participation) if (!pInfo->InAction)
|
|
// Not dead
|
|
if (!pInfo->HasDied)
|
|
// Highest experience
|
|
if (!pHiExp || (pInfo->Experience>pHiExp->Experience))
|
|
// Set this
|
|
pHiExp=pInfo;
|
|
|
|
// Found
|
|
if (pHiExp)
|
|
{
|
|
pHiExp->Recruit();
|
|
return pHiExp;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
C4ObjectInfo* C4ObjectInfoList::New(C4ID n_id, C4DefList *pDefs)
|
|
{
|
|
C4ObjectInfo *pInfo;
|
|
// Create new info object
|
|
if (!(pInfo = new C4ObjectInfo)) return NULL;
|
|
// Default type clonk if none specified
|
|
if (n_id == C4ID::None) n_id = C4ID::Clonk;
|
|
// Check type valid and def available
|
|
C4Def *pDef = NULL;
|
|
if (pDefs)
|
|
if (!(pDef = pDefs->ID2Def(n_id)))
|
|
{ delete pInfo; return false; }
|
|
// Set name source
|
|
const char *cpNames = Game.Names.GetData();
|
|
if (pDef->pClonkNames) cpNames = pDef->pClonkNames->GetData();
|
|
// Default by type
|
|
((C4ObjectInfoCore*)pInfo)->Default(n_id, pDefs, cpNames);
|
|
// Set birthday
|
|
pInfo->Birthday=time(NULL);
|
|
// Make valid names
|
|
MakeValidName(pInfo->Name);
|
|
// Add
|
|
Add(pInfo);
|
|
++iNumCreated;
|
|
return pInfo;
|
|
}
|
|
|
|
void C4ObjectInfoList::Evaluate()
|
|
{
|
|
C4ObjectInfo *cinf;
|
|
for (cinf=First; cinf; cinf=cinf->Next)
|
|
cinf->Evaluate();
|
|
}
|
|
|
|
bool C4ObjectInfoList::Save(C4Group &hGroup, bool fSavegame, bool fStoreTiny, C4DefList *pDefs)
|
|
{
|
|
// Save in opposite order (for identical crew order on load)
|
|
C4ObjectInfo *pInfo;
|
|
for (pInfo = GetLast(); pInfo; pInfo = GetPrevious(pInfo))
|
|
{
|
|
// don't safe TemporaryCrew in regular player files
|
|
if (!fSavegame)
|
|
{
|
|
C4Def *pDef=C4Id2Def(pInfo->id);
|
|
if (pDef) if (pDef->TemporaryCrew) continue;
|
|
}
|
|
// save
|
|
if (!pInfo->Save(hGroup, fStoreTiny, pDefs))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
C4ObjectInfo* C4ObjectInfoList::GetIdle(const char *szByName)
|
|
{
|
|
C4ObjectInfo *pInfo;
|
|
// Find matching name, participating, alive and not in action
|
|
for (pInfo=First; pInfo; pInfo=pInfo->Next)
|
|
if (SEqualNoCase(pInfo->Name,szByName))
|
|
if (pInfo->Participation) if (!pInfo->InAction)
|
|
if (!pInfo->HasDied)
|
|
{
|
|
pInfo->Recruit();
|
|
return pInfo;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void C4ObjectInfoList::DetachFromObjects()
|
|
{
|
|
C4ObjectInfo *cinf;
|
|
for (cinf=First; cinf; cinf=cinf->Next)
|
|
::Objects.ClearInfo(cinf);
|
|
}
|
|
|
|
C4ObjectInfo* C4ObjectInfoList::GetLast()
|
|
{
|
|
C4ObjectInfo *cInfo = First;
|
|
while (cInfo && cInfo->Next) cInfo=cInfo->Next;
|
|
return cInfo;
|
|
}
|
|
|
|
C4ObjectInfo* C4ObjectInfoList::GetPrevious(C4ObjectInfo *pInfo)
|
|
{
|
|
for (C4ObjectInfo *cInfo = First; cInfo; cInfo=cInfo->Next)
|
|
if (cInfo->Next == pInfo)
|
|
return cInfo;
|
|
return NULL;
|
|
}
|
|
|
|
bool C4ObjectInfoList::IsElement(C4ObjectInfo *pInfo)
|
|
{
|
|
for (C4ObjectInfo *cInfo = First; cInfo; cInfo=cInfo->Next)
|
|
if (cInfo == pInfo) return true;
|
|
return false;
|
|
}
|
|
|
|
void C4ObjectInfoList::Strip(C4DefList &rDefs)
|
|
{
|
|
C4ObjectInfo *pInfo, *pPrev;
|
|
// Search list
|
|
for (pInfo=First, pPrev=NULL; pInfo; )
|
|
{
|
|
// Invalid?
|
|
if (!rDefs.ID2Def(pInfo->id))
|
|
{
|
|
C4ObjectInfo *pDelete = pInfo;
|
|
if (pPrev) pPrev->Next = pInfo->Next; else First = pInfo->Next;
|
|
pInfo = pInfo->Next;
|
|
delete pDelete;
|
|
}
|
|
else
|
|
{
|
|
pPrev = pInfo;
|
|
pInfo = pInfo->Next;
|
|
}
|
|
}
|
|
}
|