1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003-2005 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 #include "FileStream.h"
32 #include "Interface.h"
35 #include "EffectMgr.h"
37 #include "ResourceDesc.h"
38 #include "AnimationMgr.h"
40 #include "ImageFactory.h"
42 static void ReleaseItem(void *poi
)
44 delete ((Item
*) poi
);
47 static void ReleaseSpell(void *poi
)
49 delete ((Spell
*) poi
);
52 static void ReleaseEffect(void *poi
)
54 delete ((Effect
*) poi
);
57 static void ReleasePalette(void *poi
)
59 //we allow nulls, but we shouldn't release them
61 //as long as palette has its own refcount, this should be Release
62 ((Palette
*) poi
)->Release();
65 GEM_EXPORT GameData
* gamedata
;
69 factory
= new Factory();
77 void GameData::ClearCaches()
79 ItemCache
.RemoveAll(ReleaseItem
);
80 SpellCache
.RemoveAll(ReleaseSpell
);
81 EffectCache
.RemoveAll(ReleaseEffect
);
82 PaletteCache
.RemoveAll(ReleasePalette
);
85 Actor
*GameData::GetCreature(const char* ResRef
, unsigned int PartySlot
)
87 DataStream
* ds
= GetResource( ResRef
, IE_CRE_CLASS_ID
);
91 PluginHolder
<ActorMgr
> actormgr(IE_CRE_CLASS_ID
);
92 if (!actormgr
->Open( ds
, true )) {
95 Actor
* actor
= actormgr
->GetActor(PartySlot
);
99 int GameData::LoadCreature(const char* ResRef
, unsigned int PartySlot
, bool character
)
105 char nPath
[_MAX_PATH
], fName
[16];
106 snprintf( fName
, sizeof(fName
), "%s.chr", ResRef
);
107 PathJoin( nPath
, core
->GamePath
, "characters", fName
, NULL
);
108 FileStream
*fs
= new FileStream();
109 fs
-> Open( nPath
, true );
110 stream
= (DataStream
*) fs
;
111 PluginHolder
<ActorMgr
> actormgr(IE_CRE_CLASS_ID
);
112 if (!actormgr
->Open( stream
, true )) {
115 actor
= actormgr
->GetActor(PartySlot
);
117 actor
= GetCreature(ResRef
, PartySlot
);
124 //both fields are of length 9, make this sure!
125 memcpy(actor
->Area
, core
->GetGame()->CurrentArea
, sizeof(actor
->Area
) );
126 if (actor
->BaseStats
[IE_STATE_ID
] & STATE_DEAD
) {
127 actor
->SetStance( IE_ANI_TWITCH
);
129 actor
->SetStance( IE_ANI_AWAKE
);
131 actor
->SetOrientation( 0, false );
133 if ( PartySlot
!= 0 ) {
134 return core
->GetGame()->JoinParty( actor
, JP_JOIN
|JP_INITPOS
);
137 return core
->GetGame()->AddNPC( actor
);
141 /** Loads a 2DA Table, returns -1 on error or the Table Index on success */
142 int GameData::LoadTable(const ieResRef ResRef
)
144 int ind
= GetTableIndex( ResRef
);
146 tables
[ind
].refcount
++;
149 //printf("(%s) Table not found... Loading from file\n", ResRef);
150 DataStream
* str
= GetResource( ResRef
, IE_2DA_CLASS_ID
);
154 PluginHolder
<TableMgr
> tm(IE_2DA_CLASS_ID
);
159 if (!tm
->Open( str
, true )) {
164 strncpy( t
.ResRef
, ResRef
, 8 );
167 for (size_t i
= 0; i
< tables
.size(); i
++) {
168 if (tables
[i
].refcount
== 0) {
177 tables
.push_back( t
);
178 return ( int ) tables
.size() - 1;
180 /** Gets the index of a loaded table, returns -1 on error */
181 int GameData::GetTableIndex(const char* ResRef
) const
183 for (size_t i
= 0; i
< tables
.size(); i
++) {
184 if (tables
[i
].refcount
== 0)
186 if (strnicmp( tables
[i
].ResRef
, ResRef
, 8 ) == 0)
191 /** Gets a Loaded Table by its index, returns NULL on error */
192 Holder
<TableMgr
> GameData::GetTable(unsigned int index
) const
194 if (index
>= tables
.size()) {
197 if (tables
[index
].refcount
== 0) {
200 return tables
[index
].tm
;
203 /** Frees a Loaded Table, returns false on error, true on success */
204 bool GameData::DelTable(unsigned int index
)
206 if (index
==0xffffffff) {
210 if (index
>= tables
.size()) {
213 if (tables
[index
].refcount
== 0) {
216 tables
[index
].refcount
--;
217 if (tables
[index
].refcount
== 0)
218 if (tables
[index
].tm
)
219 tables
[index
].tm
.release();
223 Palette
*GameData::GetPalette(const ieResRef resname
)
225 Palette
*palette
= (Palette
*) PaletteCache
.GetResource(resname
);
229 //additional hack for allowing NULL's
230 if (PaletteCache
.RefCount(resname
)!=-1) {
233 ResourceHolder
<ImageMgr
> im(resname
);
235 PaletteCache
.SetAt(resname
, NULL
);
239 palette
= new Palette();
240 im
->GetPalette(256,palette
->col
);
242 PaletteCache
.SetAt(resname
, (void *) palette
);
246 void GameData::FreePalette(Palette
*&pal
, const ieResRef name
)
253 if (!name
|| !name
[0]) {
255 printf("Palette is supposed to be named, but got no name!\n");
264 printf("Unnamed palette, it should be %s!\n", name
);
267 res
=PaletteCache
.DecRef((void *) pal
, name
, true);
269 printMessage( "Core", "Corrupted Palette cache encountered (reference count went below zero), ", LIGHT_RED
);
270 printf( "Palette name is: %.8s\n", name
);
279 Item
* GameData::GetItem(const ieResRef resname
)
281 Item
*item
= (Item
*) ItemCache
.GetResource(resname
);
285 DataStream
* str
= GetResource( resname
, IE_ITM_CLASS_ID
);
286 PluginHolder
<ItemMgr
> sm(IE_ITM_CLASS_ID
);
291 if (!sm
->Open( str
, true )) {
296 //this is required for storing the 'source'
297 strnlwrcpy(item
->Name
, resname
, 8);
303 ItemCache
.SetAt(resname
, (void *) item
);
307 //you can supply name for faster access
308 void GameData::FreeItem(Item
const *itm
, const ieResRef name
, bool free
)
312 res
=ItemCache
.DecRef((void *) itm
, name
, free
);
314 printMessage( "Core", "Corrupted Item cache encountered (reference count went below zero), ", LIGHT_RED
);
315 printf( "Item name is: %.8s\n", name
);
319 if (free
) delete itm
;
322 Spell
* GameData::GetSpell(const ieResRef resname
, bool silent
)
324 Spell
*spell
= (Spell
*) SpellCache
.GetResource(resname
);
328 DataStream
* str
= GetResource( resname
, IE_SPL_CLASS_ID
, silent
);
329 PluginHolder
<SpellMgr
> sm(IE_SPL_CLASS_ID
);
334 if (!sm
->Open( str
, true )) {
339 //this is required for storing the 'source'
340 strnlwrcpy(spell
->Name
, resname
, 8);
341 sm
->GetSpell( spell
, silent
);
346 SpellCache
.SetAt(resname
, (void *) spell
);
350 void GameData::FreeSpell(Spell
*spl
, const ieResRef name
, bool free
)
354 res
=SpellCache
.DecRef((void *) spl
, name
, free
);
356 printMessage( "Core", "Corrupted Spell cache encountered (reference count went below zero), ", LIGHT_RED
);
357 printf( "Spell name is: %.8s or %.8s\n", name
, spl
->Name
);
361 if (free
) delete spl
;
364 Effect
* GameData::GetEffect(const ieResRef resname
)
366 Effect
*effect
= (Effect
*) EffectCache
.GetResource(resname
);
370 DataStream
* str
= GetResource( resname
, IE_EFF_CLASS_ID
);
371 PluginHolder
<EffectMgr
> em(IE_EFF_CLASS_ID
);
376 if (!em
->Open( str
, true )) {
380 effect
= em
->GetEffect(new Effect() );
381 if (effect
== NULL
) {
385 EffectCache
.SetAt(resname
, (void *) effect
);
389 void GameData::FreeEffect(Effect
*eff
, const ieResRef name
, bool free
)
393 res
=EffectCache
.DecRef((void *) eff
, name
, free
);
395 printMessage( "Core", "Corrupted Effect cache encountered (reference count went below zero), ", LIGHT_RED
);
396 printf( "Effect name is: %.8s\n", name
);
400 if (free
) delete eff
;
403 //if the default setup doesn't fit for an animation
404 //create a vvc for it!
405 ScriptedAnimation
* GameData::GetScriptedAnimation( const char *effect
, bool doublehint
)
407 ScriptedAnimation
*ret
= NULL
;
409 if (Exists( effect
, IE_VVC_CLASS_ID
) ) {
410 DataStream
*ds
= GetResource( effect
, IE_VVC_CLASS_ID
);
411 ret
= new ScriptedAnimation(ds
, true);
413 AnimationFactory
*af
= (AnimationFactory
*)
414 GetFactoryResource( effect
, IE_BAM_CLASS_ID
, IE_NORMAL
);
416 ret
= new ScriptedAnimation();
417 ret
->LoadAnimationFactory( af
, doublehint
?2:0);
421 strnlwrcpy(ret
->ResName
, effect
, 8);
426 // Return single BAM frame as a sprite. Use if you want one frame only,
427 // otherwise it's not efficient
428 Sprite2D
* GameData::GetBAMSprite(const ieResRef ResRef
, int cycle
, int frame
)
431 AnimationFactory
* af
= ( AnimationFactory
* )
432 GetFactoryResource( ResRef
, IE_BAM_CLASS_ID
, IE_NORMAL
);
435 tspr
= af
->GetFrameWithoutCycle( (unsigned short) frame
);
437 tspr
= af
->GetFrame( (unsigned short) frame
, (unsigned char) cycle
);
441 void* GameData::GetFactoryResource(const char* resname
, SClass_ID type
,
442 unsigned char mode
, bool silent
)
444 int fobjindex
= factory
->IsLoaded(resname
,type
);
446 if ( fobjindex
!= -1)
447 return factory
->GetFactoryObject( fobjindex
);
450 if (!strcmp(resname
, ""))
454 case IE_BAM_CLASS_ID
:
456 DataStream
* ret
= GetResource( resname
, type
, silent
);
458 PluginHolder
<AnimationMgr
> ani(IE_BAM_CLASS_ID
);
461 ani
->Open( ret
, true );
462 AnimationFactory
* af
= ani
->GetAnimationFactory( resname
, mode
);
463 factory
->AddFactoryObject( af
);
468 case IE_BMP_CLASS_ID
:
470 ResourceHolder
<ImageMgr
> img(resname
);
472 ImageFactory
* fact
= img
->GetImageFactory( resname
);
473 factory
->AddFactoryObject( fact
);
481 printMessage( "KEYImporter", " ", WHITE
);
482 printf( "%s files are not supported.\n", core
->TypeExt( type
) );