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.
24 #include "AnimationMgr.h"
27 #include "EffectMgr.h"
29 #include "FileStream.h"
31 #include "ImageFactory.h"
33 #include "Interface.h"
36 #include "ResourceDesc.h"
39 #include "Scriptable/Actor.h"
43 static void ReleaseItem(void *poi
)
45 delete ((Item
*) poi
);
48 static void ReleaseSpell(void *poi
)
50 delete ((Spell
*) poi
);
53 static void ReleaseEffect(void *poi
)
55 delete ((Effect
*) poi
);
58 static void ReleasePalette(void *poi
)
60 //we allow nulls, but we shouldn't release them
62 //as long as palette has its own refcount, this should be Release
63 ((Palette
*) poi
)->Release();
66 GEM_EXPORT GameData
* gamedata
;
70 factory
= new Factory();
78 void GameData::ClearCaches()
80 ItemCache
.RemoveAll(ReleaseItem
);
81 SpellCache
.RemoveAll(ReleaseSpell
);
82 EffectCache
.RemoveAll(ReleaseEffect
);
83 PaletteCache
.RemoveAll(ReleasePalette
);
86 Actor
*GameData::GetCreature(const char* ResRef
, unsigned int PartySlot
)
88 DataStream
* ds
= GetResource( ResRef
, IE_CRE_CLASS_ID
);
92 PluginHolder
<ActorMgr
> actormgr(IE_CRE_CLASS_ID
);
93 if (!actormgr
->Open( ds
, true )) {
96 Actor
* actor
= actormgr
->GetActor(PartySlot
);
100 int GameData::LoadCreature(const char* ResRef
, unsigned int PartySlot
, bool character
)
106 char nPath
[_MAX_PATH
], fName
[16];
107 snprintf( fName
, sizeof(fName
), "%s.chr", ResRef
);
108 PathJoin( nPath
, core
->GamePath
, "characters", fName
, NULL
);
109 FileStream
*fs
= new FileStream();
110 fs
-> Open( nPath
, true );
111 stream
= (DataStream
*) fs
;
112 PluginHolder
<ActorMgr
> actormgr(IE_CRE_CLASS_ID
);
113 if (!actormgr
->Open( stream
, true )) {
116 actor
= actormgr
->GetActor(PartySlot
);
118 actor
= GetCreature(ResRef
, PartySlot
);
125 //both fields are of length 9, make this sure!
126 memcpy(actor
->Area
, core
->GetGame()->CurrentArea
, sizeof(actor
->Area
) );
127 if (actor
->BaseStats
[IE_STATE_ID
] & STATE_DEAD
) {
128 actor
->SetStance( IE_ANI_TWITCH
);
130 actor
->SetStance( IE_ANI_AWAKE
);
132 actor
->SetOrientation( 0, false );
134 if ( PartySlot
!= 0 ) {
135 return core
->GetGame()->JoinParty( actor
, JP_JOIN
|JP_INITPOS
);
138 return core
->GetGame()->AddNPC( actor
);
142 /** Loads a 2DA Table, returns -1 on error or the Table Index on success */
143 int GameData::LoadTable(const ieResRef ResRef
)
145 int ind
= GetTableIndex( ResRef
);
147 tables
[ind
].refcount
++;
150 //printf("(%s) Table not found... Loading from file\n", ResRef);
151 DataStream
* str
= GetResource( ResRef
, IE_2DA_CLASS_ID
);
155 PluginHolder
<TableMgr
> tm(IE_2DA_CLASS_ID
);
160 if (!tm
->Open( str
, true )) {
165 strncpy( t
.ResRef
, ResRef
, 8 );
168 for (size_t i
= 0; i
< tables
.size(); i
++) {
169 if (tables
[i
].refcount
== 0) {
178 tables
.push_back( t
);
179 return ( int ) tables
.size() - 1;
181 /** Gets the index of a loaded table, returns -1 on error */
182 int GameData::GetTableIndex(const char* ResRef
) const
184 for (size_t i
= 0; i
< tables
.size(); i
++) {
185 if (tables
[i
].refcount
== 0)
187 if (strnicmp( tables
[i
].ResRef
, ResRef
, 8 ) == 0)
192 /** Gets a Loaded Table by its index, returns NULL on error */
193 Holder
<TableMgr
> GameData::GetTable(unsigned int index
) const
195 if (index
>= tables
.size()) {
198 if (tables
[index
].refcount
== 0) {
201 return tables
[index
].tm
;
204 /** Frees a Loaded Table, returns false on error, true on success */
205 bool GameData::DelTable(unsigned int index
)
207 if (index
==0xffffffff) {
211 if (index
>= tables
.size()) {
214 if (tables
[index
].refcount
== 0) {
217 tables
[index
].refcount
--;
218 if (tables
[index
].refcount
== 0)
219 if (tables
[index
].tm
)
220 tables
[index
].tm
.release();
224 Palette
*GameData::GetPalette(const ieResRef resname
)
226 Palette
*palette
= (Palette
*) PaletteCache
.GetResource(resname
);
230 //additional hack for allowing NULL's
231 if (PaletteCache
.RefCount(resname
)!=-1) {
234 ResourceHolder
<ImageMgr
> im(resname
);
236 PaletteCache
.SetAt(resname
, NULL
);
240 palette
= new Palette();
241 im
->GetPalette(256,palette
->col
);
243 PaletteCache
.SetAt(resname
, (void *) palette
);
247 void GameData::FreePalette(Palette
*&pal
, const ieResRef name
)
254 if (!name
|| !name
[0]) {
256 printf("Palette is supposed to be named, but got no name!\n");
265 printf("Unnamed palette, it should be %s!\n", name
);
268 res
=PaletteCache
.DecRef((void *) pal
, name
, true);
270 printMessage( "Core", "Corrupted Palette cache encountered (reference count went below zero), ", LIGHT_RED
);
271 printf( "Palette name is: %.8s\n", name
);
280 Item
* GameData::GetItem(const ieResRef resname
)
282 Item
*item
= (Item
*) ItemCache
.GetResource(resname
);
286 DataStream
* str
= GetResource( resname
, IE_ITM_CLASS_ID
);
287 PluginHolder
<ItemMgr
> sm(IE_ITM_CLASS_ID
);
292 if (!sm
->Open( str
, true )) {
297 //this is required for storing the 'source'
298 strnlwrcpy(item
->Name
, resname
, 8);
304 ItemCache
.SetAt(resname
, (void *) item
);
308 //you can supply name for faster access
309 void GameData::FreeItem(Item
const *itm
, const ieResRef name
, bool free
)
313 res
=ItemCache
.DecRef((void *) itm
, name
, free
);
315 printMessage( "Core", "Corrupted Item cache encountered (reference count went below zero), ", LIGHT_RED
);
316 printf( "Item name is: %.8s\n", name
);
320 if (free
) delete itm
;
323 Spell
* GameData::GetSpell(const ieResRef resname
, bool silent
)
325 Spell
*spell
= (Spell
*) SpellCache
.GetResource(resname
);
329 DataStream
* str
= GetResource( resname
, IE_SPL_CLASS_ID
, silent
);
330 PluginHolder
<SpellMgr
> sm(IE_SPL_CLASS_ID
);
335 if (!sm
->Open( str
, true )) {
340 //this is required for storing the 'source'
341 strnlwrcpy(spell
->Name
, resname
, 8);
342 sm
->GetSpell( spell
, silent
);
347 SpellCache
.SetAt(resname
, (void *) spell
);
351 void GameData::FreeSpell(Spell
*spl
, const ieResRef name
, bool free
)
355 res
=SpellCache
.DecRef((void *) spl
, name
, free
);
357 printMessage( "Core", "Corrupted Spell cache encountered (reference count went below zero), ", LIGHT_RED
);
358 printf( "Spell name is: %.8s or %.8s\n", name
, spl
->Name
);
362 if (free
) delete spl
;
365 Effect
* GameData::GetEffect(const ieResRef resname
)
367 Effect
*effect
= (Effect
*) EffectCache
.GetResource(resname
);
371 DataStream
* str
= GetResource( resname
, IE_EFF_CLASS_ID
);
372 PluginHolder
<EffectMgr
> em(IE_EFF_CLASS_ID
);
377 if (!em
->Open( str
, true )) {
381 effect
= em
->GetEffect(new Effect() );
382 if (effect
== NULL
) {
386 EffectCache
.SetAt(resname
, (void *) effect
);
390 void GameData::FreeEffect(Effect
*eff
, const ieResRef name
, bool free
)
394 res
=EffectCache
.DecRef((void *) eff
, name
, free
);
396 printMessage( "Core", "Corrupted Effect cache encountered (reference count went below zero), ", LIGHT_RED
);
397 printf( "Effect name is: %.8s\n", name
);
401 if (free
) delete eff
;
404 //if the default setup doesn't fit for an animation
405 //create a vvc for it!
406 ScriptedAnimation
* GameData::GetScriptedAnimation( const char *effect
, bool doublehint
)
408 ScriptedAnimation
*ret
= NULL
;
410 if (Exists( effect
, IE_VVC_CLASS_ID
) ) {
411 DataStream
*ds
= GetResource( effect
, IE_VVC_CLASS_ID
);
412 ret
= new ScriptedAnimation(ds
, true);
414 AnimationFactory
*af
= (AnimationFactory
*)
415 GetFactoryResource( effect
, IE_BAM_CLASS_ID
, IE_NORMAL
);
417 ret
= new ScriptedAnimation();
418 ret
->LoadAnimationFactory( af
, doublehint
?2:0);
422 strnlwrcpy(ret
->ResName
, effect
, 8);
427 // Return single BAM frame as a sprite. Use if you want one frame only,
428 // otherwise it's not efficient
429 Sprite2D
* GameData::GetBAMSprite(const ieResRef ResRef
, int cycle
, int frame
)
432 AnimationFactory
* af
= ( AnimationFactory
* )
433 GetFactoryResource( ResRef
, IE_BAM_CLASS_ID
, IE_NORMAL
);
436 tspr
= af
->GetFrameWithoutCycle( (unsigned short) frame
);
438 tspr
= af
->GetFrame( (unsigned short) frame
, (unsigned char) cycle
);
442 void* GameData::GetFactoryResource(const char* resname
, SClass_ID type
,
443 unsigned char mode
, bool silent
)
445 int fobjindex
= factory
->IsLoaded(resname
,type
);
447 if ( fobjindex
!= -1)
448 return factory
->GetFactoryObject( fobjindex
);
451 if (!strcmp(resname
, ""))
455 case IE_BAM_CLASS_ID
:
457 DataStream
* ret
= GetResource( resname
, type
, silent
);
459 PluginHolder
<AnimationMgr
> ani(IE_BAM_CLASS_ID
);
462 ani
->Open( ret
, true );
463 AnimationFactory
* af
= ani
->GetAnimationFactory( resname
, mode
);
464 factory
->AddFactoryObject( af
);
469 case IE_BMP_CLASS_ID
:
471 ResourceHolder
<ImageMgr
> img(resname
);
473 ImageFactory
* fact
= img
->GetImageFactory( resname
);
474 factory
->AddFactoryObject( fact
);
482 printMessage( "KEYImporter", " ", WHITE
);
483 printf( "%s files are not supported.\n", core
->TypeExt( type
) );