Bläddra i källkod

* more constTransitivePointers in GameInfo, separated client GUI classes from it, moved def handlers from CGDefInfo

mateuszb 15 år sedan
förälder
incheckning
b15deaa203

+ 2 - 2
client/AdventureMapButton.cpp

@@ -142,7 +142,7 @@ void AdventureMapButton::clickLeft(tribool down, bool previousState)
 
 	if (down) 
 	{
-		CGI->soundh->playSound(soundBase::button);
+		CCS->soundh->playSound(soundBase::button);
 		state = 1;
 	} 
 	else if(hoverable && hovered)
@@ -295,7 +295,7 @@ void CHighlightableButton::clickLeft(tribool down, bool previousState)
 		return;
 	if (down) 
 	{
-		CGI->soundh->playSound(soundBase::button);
+		CCS->soundh->playSound(soundBase::button);
 		state = 1;
 	} 
 	else

+ 37 - 36
client/CAdvmapInterface.cpp

@@ -29,6 +29,7 @@
 #include "../lib/VCMI_Lib.h"
 #include "../hch/CSpellHandler.h"
 #include <boost/foreach.hpp>
+#include "../hch/CSoundBase.h"
 
 #ifdef _MSC_VER
 #pragma warning (disable : 4355)
@@ -491,7 +492,7 @@ void CTerrainRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 
 	if(tHovered != pom) //tile outside the map
 	{
-		CGI->curh->changeGraphic(0, 0);
+		CCS->curh->changeGraphic(0, 0);
 		return;
 	}
 
@@ -507,7 +508,7 @@ void CTerrainRect::hover(bool on)
 	if (!on)
 	{
 		adventureInt->statusbar.clear();
-		CGI->curh->changeGraphic(0,0);
+		CCS->curh->changeGraphic(0,0);
 	}
 	//Hoverable::hover(on);
 }
@@ -1329,7 +1330,7 @@ void CAdvMapInt::deactivate()
 	deactivateMouseMove();
 	scrollingDir = 0;
 
-	CGI->curh->changeGraphic(0,0);
+	CCS->curh->changeGraphic(0,0);
 	kingOverview.deactivate();
 	underground.deactivate();
 	questlog.deactivate();
@@ -1857,18 +1858,18 @@ void CAdvMapInt::tileHovered(const int3 &tile)
 		{
 		case Spells::SCUTTLE_BOAT:
 			if(objAtTile && objAtTile->ID == 8)
-				CGI->curh->changeGraphic(0, 42);
+				CCS->curh->changeGraphic(0, 42);
 			else
-				CGI->curh->changeGraphic(0, 0);
+				CCS->curh->changeGraphic(0, 0);
 			return;
 		case Spells::DIMENSION_DOOR:
 			{
 				const TerrainTile *t = LOCPLINT->cb->getTileInfo(tile);
 				int3 hpos = selection->getSightCenter();
 				if((!t  ||  t->isClear(LOCPLINT->cb->getTileInfo(hpos)))   &&   isInScreenRange(hpos, tile))
-					CGI->curh->changeGraphic(0, 41);
+					CCS->curh->changeGraphic(0, 41);
 				else
-					CGI->curh->changeGraphic(0, 0);
+					CCS->curh->changeGraphic(0, 0);
 				return;
 			}
 		}
@@ -1881,12 +1882,12 @@ void CAdvMapInt::tileHovered(const int3 &tile)
 		if(objAtTile)
 		{
 			if(objAtTile->ID == TOWNI_TYPE && LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, objAtTile->tempOwner))
-				CGI->curh->changeGraphic(0, 3);
+				CCS->curh->changeGraphic(0, 3);
 			else if(objAtTile->ID == HEROI_TYPE && objAtTile->tempOwner == LOCPLINT->playerID)
-				CGI->curh->changeGraphic(0, 2);
+				CCS->curh->changeGraphic(0, 2);
 		}
 		else
-			CGI->curh->changeGraphic(0, 0);
+			CCS->curh->changeGraphic(0, 0);
 	}
 	else if(const CGHeroInstance *h = curHero())
 	{
@@ -1897,18 +1898,18 @@ void CAdvMapInt::tileHovered(const int3 &tile)
 				if(!LOCPLINT->cb->getPlayerRelations( LOCPLINT->playerID, objAtTile->tempOwner)) //enemy hero
 				{
 					if(accessible)
-						CGI->curh->changeGraphic(0, 5 + turns*6);
+						CCS->curh->changeGraphic(0, 5 + turns*6);
 					else
-						CGI->curh->changeGraphic(0, 0);
+						CCS->curh->changeGraphic(0, 0);
 				}
 				else //our or ally hero
 				{
 					if(selection == objAtTile)
-						CGI->curh->changeGraphic(0, 2);
+						CCS->curh->changeGraphic(0, 2);
 					else if(accessible)
-						CGI->curh->changeGraphic(0, 8 + turns*6);
+						CCS->curh->changeGraphic(0, 8 + turns*6);
 					else
-						CGI->curh->changeGraphic(0, 2);
+						CCS->curh->changeGraphic(0, 2);
 				}
 			}
 			else if(objAtTile->ID == TOWNI_TYPE)
@@ -1921,30 +1922,30 @@ void CAdvMapInt::tileHovered(const int3 &tile)
 
 						// Show movement cursor for unguarded enemy towns, otherwise attack cursor.
 						if (townObj && !townObj->stacksCount())
-							CGI->curh->changeGraphic(0, 9 + turns*6);
+							CCS->curh->changeGraphic(0, 9 + turns*6);
 						else
-							CGI->curh->changeGraphic(0, 5 + turns*6);
+							CCS->curh->changeGraphic(0, 5 + turns*6);
 
 					} 
 					else 
 					{
-						CGI->curh->changeGraphic(0, 0);
+						CCS->curh->changeGraphic(0, 0);
 					}
 				}
 				else //our or ally town
 				{
 					if(accessible)
-						CGI->curh->changeGraphic(0, 9 + turns*6);
+						CCS->curh->changeGraphic(0, 9 + turns*6);
 					else
-						CGI->curh->changeGraphic(0, 3);
+						CCS->curh->changeGraphic(0, 3);
 				}
 			}
 			else if(objAtTile->ID == 8) //boat
 			{
 				if(accessible)
-					CGI->curh->changeGraphic(0, 6 + turns*6);
+					CCS->curh->changeGraphic(0, 6 + turns*6);
 				else
-					CGI->curh->changeGraphic(0, 0);
+					CCS->curh->changeGraphic(0, 0);
 			}
 			else if (objAtTile->ID == 33 || objAtTile->ID == 219) // Garrison
 			{
@@ -1955,28 +1956,28 @@ void CAdvMapInt::tileHovered(const int3 &tile)
 					// Show battle cursor for guarded enemy garrisons, otherwise movement cursor.
 					if (garrObj&&  garrObj->stacksCount() 
 						&& !LOCPLINT->cb->getPlayerRelations( LOCPLINT->playerID, garrObj->tempOwner) )
-						CGI->curh->changeGraphic(0, 5 + turns*6);
+						CCS->curh->changeGraphic(0, 5 + turns*6);
 					else
-						CGI->curh->changeGraphic(0, 9 + turns*6);
+						CCS->curh->changeGraphic(0, 9 + turns*6);
 				} 
 				else 
-					CGI->curh->changeGraphic(0, 0);
+					CCS->curh->changeGraphic(0, 0);
 			}
 			else if (guardingCreature && accessible) //(objAtTile->ID == 54) //monster
 			{
-				CGI->curh->changeGraphic(0, 5 + turns*6);
+				CCS->curh->changeGraphic(0, 5 + turns*6);
 			}
 			else
 			{
 				if(accessible)
 				{
 					if(pnode->land)
-						CGI->curh->changeGraphic(0, 9 + turns*6);
+						CCS->curh->changeGraphic(0, 9 + turns*6);
 					else
-						CGI->curh->changeGraphic(0, 28 + turns);
+						CCS->curh->changeGraphic(0, 28 + turns);
 				}
 				else
-					CGI->curh->changeGraphic(0, 0);
+					CCS->curh->changeGraphic(0, 0);
 			}
 		} 
 		else //no objs 
@@ -1984,27 +1985,27 @@ void CAdvMapInt::tileHovered(const int3 &tile)
 			if(accessible && pnode->accessible != CGPathNode::FLYABLE)
 			{
 				if (guardingCreature) {
-					CGI->curh->changeGraphic(0, 5 + turns*6);
+					CCS->curh->changeGraphic(0, 5 + turns*6);
 				} else {
 					if(pnode->land)
 					{
 						if(LOCPLINT->cb->getTileInfo(h->getPosition(false))->tertype != TerrainTile::water)
-							CGI->curh->changeGraphic(0, 4 + turns*6);
+							CCS->curh->changeGraphic(0, 4 + turns*6);
 						else
-							CGI->curh->changeGraphic(0, 7 + turns*6); //anchor
+							CCS->curh->changeGraphic(0, 7 + turns*6); //anchor
 					}
 					else
-						CGI->curh->changeGraphic(0, 6 + turns*6);
+						CCS->curh->changeGraphic(0, 6 + turns*6);
 				}
 			}
 			else
-				CGI->curh->changeGraphic(0, 0);
+				CCS->curh->changeGraphic(0, 0);
 		}
 	}
 
 	if(const IShipyard *shipyard = ourInaccessibleShipyard(objAtTile))
 	{
-		CGI->curh->changeGraphic(0, 6);
+		CCS->curh->changeGraphic(0, 6);
 	}
 }
 
@@ -2079,7 +2080,7 @@ const IShipyard * CAdvMapInt::ourInaccessibleShipyard(const CGObjectInstance *ob
 {
 	const IShipyard *ret = IShipyard::castFrom(obj);
 
-	if(!ret || obj->tempOwner != player || CGI->curh->mode || (CGI->curh->number != 6 && CGI->curh->number != 0))
+	if(!ret || obj->tempOwner != player || CCS->curh->mode || (CCS->curh->number != 6 && CCS->curh->number != 0))
 		return NULL;
 
 	return ret;

+ 62 - 62
client/CBattleInterface.cpp

@@ -518,13 +518,13 @@ bool CDefenceAnim::init()
 	//initializing
 	if(killed)
 	{
-		CGI->soundh->playSound(battle_sound(attacked->getCreature(), killed));
+		CCS->soundh->playSound(battle_sound(attacked->getCreature(), killed));
 		owner->creAnims[stackID]->setType(5); //death
 	}
 	else
 	{
 		// TODO: this block doesn't seems correct if the unit is defending.
-		CGI->soundh->playSound(battle_sound(attacked->getCreature(), wince));
+		CCS->soundh->playSound(battle_sound(attacked->getCreature(), wince));
 		owner->creAnims[stackID]->setType(3); //getting hit
 	}
 
@@ -628,7 +628,7 @@ bool CBattleStackMoved::init()
 	//unit reversed
 
 	if(owner->moveSh <= 0)
-		owner->moveSh = CGI->soundh->playSound(battle_sound(movedStack->getCreature(), move), -1);
+		owner->moveSh = CCS->soundh->playSound(battle_sound(movedStack->getCreature(), move), -1);
 
 	//step shift calculation
 	posX = owner->creAnims[stackID]->pos.x, posY = owner->creAnims[stackID]->pos.y; // for precise calculations ;]
@@ -716,7 +716,7 @@ void CBattleStackMoved::endAnim()
 
 	if(owner->moveSh >= 0)
 	{
-		CGI->soundh->stopSound(owner->moveSh);
+		CCS->soundh->stopSound(owner->moveSh);
 		owner->moveSh = -1;
 	}
 
@@ -744,7 +744,7 @@ bool CBattleMoveStart::init()
 		return false;
 	}
 
-	CGI->soundh->playSound(battle_sound(movedStack->getCreature(), startMoving));
+	CCS->soundh->playSound(battle_sound(movedStack->getCreature(), startMoving));
 
 	return true;
 }
@@ -789,7 +789,7 @@ bool CBattleMoveEnd::init()
 		return false;
 	}
 
-	CGI->soundh->playSound(battle_sound(movedStack->getCreature(), endMoving));
+	CCS->soundh->playSound(battle_sound(movedStack->getCreature(), endMoving));
 
 	owner->creAnims[stackID]->setType(21);
 
@@ -811,7 +811,7 @@ void CBattleMoveEnd::endAnim()
 	if(owner->creAnims[stackID]->getType() != 5)
 		owner->creAnims[stackID]->setType(2); //resetting to default
 
-	CGI->curh->show();
+	CCS->curh->show();
 	delete this;
 }
 
@@ -830,9 +830,9 @@ void CBattleAttack::nextFrame()
 	if(owner->creAnims[stackID]->onFirstFrameInGroup())
 	{
 		if(shooting)
-			CGI->soundh->playSound(battle_sound(attackingStack->getCreature(), shoot));
+			CCS->soundh->playSound(battle_sound(attackingStack->getCreature(), shoot));
 		else
-			CGI->soundh->playSound(battle_sound(attackingStack->getCreature(), attack));
+			CCS->soundh->playSound(battle_sound(attackingStack->getCreature(), attack));
 	}
 	else if(owner->creAnims[stackID]->onLastFrameInGroup())
 	{
@@ -1507,7 +1507,7 @@ void CBattleInterface::show(SDL_Surface * to)
 			if(spellToCast) //when casting spell
 			{
 				//calculating spell schoold level
-				const CSpell & spToCast =  CGI->spellh->spells[spellToCast->additionalInfo];
+				const CSpell & spToCast =  *CGI->spellh->spells[spellToCast->additionalInfo];
 				ui8 schoolLevel = 0;
 				if( curInt->cb->battleGetStackByID(activeStack)->attackerOwned )
 				{
@@ -1768,7 +1768,7 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 		}
 		if(myNumber == -1)
 		{
-			CGI->curh->changeGraphic(1, 6);
+			CCS->curh->changeGraphic(1, 6);
 			if(console->whoSetAlter == 0)
 			{
 				console->alterTxt = "";
@@ -1787,12 +1787,12 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 						if(sactive->hasBonusOfType(Bonus::HEALER))
 						{
 							//display the possibility to heal this creature
-							CGI->curh->changeGraphic(1,17);
+							CCS->curh->changeGraphic(1,17);
 						}
 						else
 						{
 							//info about creature
-							CGI->curh->changeGraphic(1,5);
+							CCS->curh->changeGraphic(1,5);
 						}
 						//setting console text
 						char buf[500];
@@ -1811,11 +1811,11 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 						if(curInt->cb->battleHasDistancePenalty(activeStack, myNumber) ||
 							curInt->cb->battleHasWallPenalty(activeStack, myNumber))
 						{
-							CGI->curh->changeGraphic(1,15);
+							CCS->curh->changeGraphic(1,15);
 						}
 						else
 						{
-							CGI->curh->changeGraphic(1,3);
+							CCS->curh->changeGraphic(1,3);
 						}
 						//setting console text
 						char buf[500];
@@ -1830,7 +1830,7 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 					}
 					else if(isTileAttackable(myNumber)) //available enemy (melee attackable)
 					{
-						CCursorHandler *cursor = CGI->curh;
+						CCursorHandler *cursor = CCS->curh;
 						const CBattleHex &hoveredHex = bfield[myNumber];
 
 						const double subdividingAngle = 2.0*M_PI/6.0; // Divide a hex into six sectors.
@@ -1980,20 +1980,20 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 					}
 					else //unavailable enemy
 					{
-						CGI->curh->changeGraphic(1,0);
+						CCS->curh->changeGraphic(1,0);
 						console->alterTxt = "";
 						console->whoSetAlter = 0;
 					}
 				}
 				else if( sactive && sactive->hasBonusOfType(Bonus::CATAPULT) && isCatapultAttackable(myNumber) ) //catapulting
 				{
-					CGI->curh->changeGraphic(1,16);
+					CCS->curh->changeGraphic(1,16);
 					console->alterTxt = "";
 					console->whoSetAlter = 0;
 				}
 				else //empty unavailable tile
 				{
-					CGI->curh->changeGraphic(1,0);
+					CCS->curh->changeGraphic(1,0);
 					console->alterTxt = "";
 					console->whoSetAlter = 0;
 				}
@@ -2007,12 +2007,12 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 					char buf[500];
 					if(sactive->hasBonusOfType(Bonus::FLYING))
 					{
-						CGI->curh->changeGraphic(1,2);
+						CCS->curh->changeGraphic(1,2);
 						sprintf(buf, CGI->generaltexth->allTexts[295].c_str(), sactive->count == 1 ? sactive->getCreature()->nameSing.c_str() : sactive->getCreature()->namePl.c_str());
 					}
 					else
 					{
-						CGI->curh->changeGraphic(1,1);
+						CCS->curh->changeGraphic(1,1);
 						sprintf(buf, CGI->generaltexth->allTexts[294].c_str(), sactive->count == 1 ? sactive->getCreature()->nameSing.c_str() : sactive->getCreature()->namePl.c_str());
 					}
 
@@ -2035,7 +2035,7 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 		}
 		if(myNumber == -1)
 		{
-			CGI->curh->changeGraphic(1, 0);
+			CCS->curh->changeGraphic(1, 0);
 			//setting console text
 			console->alterTxt = CGI->generaltexth->allTexts[23];
 			console->whoSetAlter = 0;
@@ -2065,28 +2065,28 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 			switch(spellSelMode)
 			{
 			case 0:
-				CGI->curh->changeGraphic(3, 0);
+				CCS->curh->changeGraphic(3, 0);
 				//setting console text
 				char buf[500];
-				sprintf(buf, CGI->generaltexth->allTexts[26].c_str(), CGI->spellh->spells[spellToCast->additionalInfo].name.c_str());
+				sprintf(buf, CGI->generaltexth->allTexts[26].c_str(), CGI->spellh->spells[spellToCast->additionalInfo]->name.c_str());
 				console->alterTxt = buf;
 				console->whoSetAlter = 0;
 				break;
 			case 1: case 2: case 3:
 				if( whichCase )
 				{
-					CGI->curh->changeGraphic(3, 0);
+					CCS->curh->changeGraphic(3, 0);
 					//setting console text
 					char buf[500];
 					std::string creName = stackUnder->count > 1 ? stackUnder->getCreature()->namePl : stackUnder->getCreature()->nameSing;
-						sprintf(buf, CGI->generaltexth->allTexts[27].c_str(), CGI->spellh->spells[spellToCast->additionalInfo].name.c_str(), creName.c_str());
+						sprintf(buf, CGI->generaltexth->allTexts[27].c_str(), CGI->spellh->spells[spellToCast->additionalInfo]->name.c_str(), creName.c_str());
 					console->alterTxt = buf;
 					console->whoSetAlter = 0;
 					break;
 				}
 				else
 				{
-					CGI->curh->changeGraphic(1, 0);
+					CCS->curh->changeGraphic(1, 0);
 					//setting console text
 					console->alterTxt = CGI->generaltexth->allTexts[23];
 					console->whoSetAlter = 0;
@@ -2095,11 +2095,11 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 			case 4: //TODO: implement this case
 				if( blockedByObstacle(myNumber) )
 				{
-					CGI->curh->changeGraphic(3, 0);
+					CCS->curh->changeGraphic(3, 0);
 				}
 				else
 				{
-					CGI->curh->changeGraphic(1, 0);
+					CCS->curh->changeGraphic(1, 0);
 				}
 				break;
 			}
@@ -2120,7 +2120,7 @@ void CBattleInterface::bOptionsf()
 	if(spellDestSelectMode) //we are casting a spell
 		return;
 
-	CGI->curh->changeGraphic(0,0);
+	CCS->curh->changeGraphic(0,0);
 
 	SDL_Rect temp_rect = genRect(431, 481, 160, 84);
 	CBattleOptionsWindow * optionsWin = new CBattleOptionsWindow(temp_rect, this);
@@ -2166,7 +2166,7 @@ void CBattleInterface::bFleef()
 void CBattleInterface::reallyFlee()
 {
 	giveCommand(4,0,0);
-	CGI->curh->changeGraphic(0, 0);
+	CCS->curh->changeGraphic(0, 0);
 }
 
 void CBattleInterface::bAutofightf()
@@ -2180,7 +2180,7 @@ void CBattleInterface::bSpellf()
 	if(spellDestSelectMode) //we are casting a spell
 		return;
 
-	CGI->curh->changeGraphic(0,0);
+	CCS->curh->changeGraphic(0,0);
 
 	const CGHeroInstance * chi = NULL;
 	if(attackingHeroInstance->tempOwner == curInt->playerID)
@@ -2423,7 +2423,7 @@ void CBattleInterface::hexLclicked(int whichOne)
 				if(!blockedByObstacle(whichOne))
 					allowCasting = false;
 			case 5: //teleport
-				const CSpell *s = &CGI->spellh->spells[spellToCast->additionalInfo];
+				const CSpell *s = CGI->spellh->spells[spellToCast->additionalInfo];
 				ui8 skill = getActiveHero()->getSpellSchoolLevel(s); //skill level
 				if (!curInt->cb->battleCanTeleportTo(activeStack, whichOne, skill))
 				{
@@ -2446,7 +2446,7 @@ void CBattleInterface::hexLclicked(int whichOne)
 			{
 				if(std::find(shadedHexes.begin(),shadedHexes.end(),whichOne)!=shadedHexes.end())// and it's in our range
 				{
-					CGI->curh->changeGraphic(1, 6); //cursor should be changed
+					CCS->curh->changeGraphic(1, 6); //cursor should be changed
 					if(curInt->cb->battleGetStackByID(activeStack)->doubleWide())
 					{
 						std::vector<int> acc = curInt->cb->battleGetAvailableHexes(activeStack, false);
@@ -2469,14 +2469,14 @@ void CBattleInterface::hexLclicked(int whichOne)
 			else if(dest->owner != actSt->owner
 				&& curInt->cb->battleCanShoot(activeStack, whichOne) ) //shooting
 			{
-				CGI->curh->changeGraphic(1, 6); //cursor should be changed
+				CCS->curh->changeGraphic(1, 6); //cursor should be changed
 				giveCommand(7,whichOne,activeStack);
 			}
 			else if(dest->owner != actSt->owner) //attacking
 			{
 				const CStack * actStack = curInt->cb->battleGetStackByID(activeStack);
 				int attackFromHex = -1; //hex from which we will attack chosen stack
-				switch(CGI->curh->number)
+				switch(CCS->curh->number)
 				{
 				case 12: //from bottom right
 					{
@@ -2622,7 +2622,7 @@ void CBattleInterface::hexLclicked(int whichOne)
 				{
 					giveCommand(6, attackFromHex, activeStack, whichOne);
 					
-					CGI->curh->changeGraphic(1, 6); //cursor should be changed
+					CCS->curh->changeGraphic(1, 6); //cursor should be changed
 				}
 
 			}
@@ -2630,7 +2630,7 @@ void CBattleInterface::hexLclicked(int whichOne)
 			{
 				giveCommand(12, whichOne, activeStack); //command healing
 
-				CGI->curh->changeGraphic(1, 6); //cursor should be changed
+				CCS->curh->changeGraphic(1, 6); //cursor should be changed
 			}
 		}
 	}
@@ -2664,17 +2664,17 @@ void CBattleInterface::battleFinished(const BattleResult& br)
 
 void CBattleInterface::displayBattleFinished()
 {
-	CGI->curh->changeGraphic(0,0);
+	CCS->curh->changeGraphic(0,0);
 	
 	SDL_Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
-	CGI->musich->stopMusic();
+	CCS->musich->stopMusic();
 	resWindow = new CBattleResultWindow(*bresult, temp_rect, this);
 	GH.pushInt(resWindow);
 }
 
 void CBattleInterface::spellCast( const BattleSpellCast * sc )
 {
-	const CSpell &spell = CGI->spellh->spells[sc->id];
+	const CSpell &spell = *CGI->spellh->spells[sc->id];
 
 	//spell opening battle is cast when no stack is active
 	if(sc->castedByHero && ( activeStack == -1 || sc->side == !curInt->cb->battleGetStackByID(activeStack)->attackerOwned) )
@@ -2682,8 +2682,8 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
 
 	std::vector< std::string > anims; //for magic arrow and ice bolt
 
-	if (spell.soundID != soundBase::invalid)
-		CGI->soundh->playSound(spell.soundID);
+	if (vstd::contains(CCS->soundh->spellSounds, &spell))
+		CCS->soundh->playSound(CCS->soundh->spellSounds[&spell]);
 
 	switch(sc->id)
 	{
@@ -2780,7 +2780,7 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
 		{
 			boost::algorithm::replace_first(text, "%s", "Creature"); //TODO: better fix
 		}
-		boost::algorithm::replace_first(text, "%s", CGI->spellh->spells[sc->id].name);
+		boost::algorithm::replace_first(text, "%s", CGI->spellh->spells[sc->id]->name);
 		boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetStackByID(*sc->affectedCres.begin(), false)->getCreature()->namePl );
 		console->addText(text);
 	}
@@ -2795,7 +2795,7 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
 		{
 			boost::algorithm::replace_first(text, "%s", "Creature"); //TODO: better fix
 		}
-		boost::algorithm::replace_first(text, "%s", CGI->spellh->spells[sc->id].name);
+		boost::algorithm::replace_first(text, "%s", CGI->spellh->spells[sc->id]->name);
 		console->addText(text);
 	}
 	if(sc->dmgToDisplay != 0)
@@ -2810,7 +2810,7 @@ void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse)
 {
 	for(std::vector<ui32>::const_iterator ci = sse.stacks.begin(); ci!=sse.stacks.end(); ++ci)
 	{
-		displayEffect(CGI->spellh->spells[sse.effect.id].mainEffectAnim, curInt->cb->battleGetStackByID(*ci)->position);
+		displayEffect(CGI->spellh->spells[sse.effect.id]->mainEffectAnim, curInt->cb->battleGetStackByID(*ci)->position);
 	}
 	if (activeStack != -1) //it can be -1 when a creature casts effect
 	{
@@ -2831,7 +2831,7 @@ void CBattleInterface::castThisSpell(int spellID)
 
 	//choosing possible tragets
 	const CGHeroInstance * castingHero = (attackingHeroInstance->tempOwner == curInt->playerID) ? attackingHeroInstance : defendingHeroInstance;
-	const CSpell & spell = CGI->spellh->spells[spellID];
+	const CSpell & spell = *CGI->spellh->spells[spellID];
 	spellSelMode = 0;
 	if(spell.attributes.find("CREATURE_TARGET") != std::string::npos) //spell to be cast on one specific creature
 	{
@@ -2898,7 +2898,7 @@ void CBattleInterface::castThisSpell(int spellID)
 	}
 	else
 	{
-		CGI->curh->changeGraphic(3, 0); 
+		CCS->curh->changeGraphic(3, 0); 
 	}
 }
 
@@ -2966,7 +2966,7 @@ void CBattleInterface::endCastingSpell()
 	delete spellToCast;
 	spellToCast = NULL;
 	spellDestSelectMode = false;
-	CGI->curh->changeGraphic(1, 6);
+	CCS->curh->changeGraphic(1, 6);
 }
 
 void CBattleInterface::showAliveStack(const CStack *stack, SDL_Surface * to)
@@ -3033,7 +3033,7 @@ void CBattleInterface::showAliveStack(const CStack *stack, SDL_Surface * to)
 			std::vector<si32> spellIds = stack->activeSpells();
 			for(std::vector<si32>::const_iterator it = spellIds.begin(); it != spellIds.end(); it++)
 			{
-				pos += CGI->spellh->spells[ *it ].positiveness;
+				pos += CGI->spellh->spells[ *it ]->positiveness;
 			}
 			if(pos > 0)
 			{
@@ -3453,7 +3453,7 @@ void CBattleHero::clickLeft(tribool down, bool previousState)
 			if(myOwner->bfield[it].hovered && myOwner->bfield[it].strictHovered)
 				return;
 		}
-		CGI->curh->changeGraphic(0,0);
+		CCS->curh->changeGraphic(0,0);
 
 		CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (conf.cc.resx - 620)/2, (conf.cc.resy - 595)/2), myHero, myOwner->curInt);
 		GH.pushInt(spellWindow);
@@ -3821,11 +3821,11 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
 			case 2: text = 302; break;
 		}
 
-		CGI->musich->playMusic(musicBase::winBattle);
+		CCS->musich->playMusic(musicBase::winBattle);
 		#ifdef _WIN32
-			CGI->videoh->open(VIDEO_WIN);
+			CCS->videoh->open(VIDEO_WIN);
 		#else
-			CGI->videoh->open(VIDEO_WIN, true);
+			CCS->videoh->open(VIDEO_WIN, true);
 		#endif
 		std::string str = CGI->generaltexth->allTexts[text];
 		
@@ -3844,22 +3844,22 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
 		{
 		case 0: //normal victory
 		{
-			CGI->musich->playMusic(musicBase::loseCombat);
-			CGI->videoh->open(VIDEO_LOSE_BATTLE_START);
+			CCS->musich->playMusic(musicBase::loseCombat);
+			CCS->videoh->open(VIDEO_LOSE_BATTLE_START);
 			CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[311], 235, 235, FONT_SMALL, zwykly, background);
 			break;
 		}
 		case 1: //flee
 		{
-			CGI->musich->playMusic(musicBase::retreatBattle);
-			CGI->videoh->open(VIDEO_RETREAT_START);
+			CCS->musich->playMusic(musicBase::retreatBattle);
+			CCS->videoh->open(VIDEO_RETREAT_START);
 			CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[310], 235, 235, FONT_SMALL, zwykly, background);
 			break;
 		}
 		case 2: //surrender
 		{
-			CGI->musich->playMusic(musicBase::surrenderBattle);
-			CGI->videoh->open(VIDEO_SURRENDER);
+			CCS->musich->playMusic(musicBase::surrenderBattle);
+			CCS->videoh->open(VIDEO_SURRENDER);
 			CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[309], 235, 220, FONT_SMALL, zwykly, background);
 			break;
 		}
@@ -3889,7 +3889,7 @@ void CBattleResultWindow::show(SDL_Surface *to)
 	if(!to)
 		to = screen;
 
-	CGI->videoh->update(107, 70, background, false, true);
+	CCS->videoh->update(107, 70, background, false, true);
 
 	SDL_BlitSurface(background, NULL, to, &pos);
 	exit->show(to);
@@ -3900,7 +3900,7 @@ void CBattleResultWindow::bExitf()
 	CPlayerInterface * intTmp = owner->curInt;
 	GH.popInts(2); //first - we; second - battle interface
 	intTmp->showingDialog->setn(false);
-	CGI->videoh->close();
+	CCS->videoh->close();
 }
 
 CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface *owner): myInt(owner)

+ 2 - 2
client/CCastleInterface.cpp

@@ -435,7 +435,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, int listPos)
 	recreateIcons();
 	cityBg = BitmapHandler::loadBitmap(graphics->townBgs[town->subID]);
 	bicons = CDefHandler::giveDefEss(graphics->buildingPics[town->subID]);
-	CGI->musich->playMusic(CGI->musich->townMusics[town->subID], -1);
+	CCS->musich->playMusic(CCS->musich->townMusics[town->subID], -1);
 }
 
 CCastleInterface::~CCastleInterface()
@@ -475,7 +475,7 @@ void CCastleInterface::close()
 	}
 	LOCPLINT->castleInt = NULL;
 	GH.popIntTotally(this);
-	CGI->musich->stopMusic(5000);
+	CCS->musich->stopMusic(5000);
 }
 
 void CCastleInterface::splitF()

+ 1 - 0
client/CGameInfo.cpp

@@ -13,6 +13,7 @@
  */
 
 const CGameInfo * CGI; //game info for general use
+CClientState * CCS;
 
 CGameInfo::CGameInfo()
 {

+ 17 - 15
client/CGameInfo.h

@@ -31,6 +31,18 @@ class CCursorHandler;
 class CGameState;
 class CVideoPlayer;
 
+
+//a class for non-mechanical client GUI classes
+class CClientState
+{
+public:
+	CSoundHandler * soundh;
+	CMusicHandler * musich;
+	CConsoleHandler * consoleh;
+	CCursorHandler * curh;
+	CVideoPlayer * videoh;
+};
+
 struct Mapa;
 
 /*
@@ -42,21 +54,16 @@ class CGameInfo
 	CGameState * state; //don't touch it in client's code
 public:
 	ConstTransitivePtr<CArtHandler> arth;
-	CHeroHandler * heroh;
-	CCreatureHandler * creh;
-	CSpellHandler * spellh;
-	CObjectHandler * objh;
-	CDefObjInfoHandler * dobjinfo;
+	ConstTransitivePtr<CHeroHandler> heroh;
+	ConstTransitivePtr<CCreatureHandler> creh;
+	ConstTransitivePtr<CSpellHandler> spellh;
+	ConstTransitivePtr<CObjectHandler> objh;
+	ConstTransitivePtr<CDefObjInfoHandler> dobjinfo;
 	CGeneralTextHandler * generaltexth;
 	CMapHandler * mh;
 	CBuildingHandler * buildh;
-	mutable CSoundHandler * soundh;
-	mutable CMusicHandler * musich;
 	CTownHandler * townh;
 	//CTownHandler * townh;
-	mutable CConsoleHandler * consoleh;
-	mutable CCursorHandler * curh;
-	mutable CVideoPlayer * videoh;
 
 	void setFromLib();
 
@@ -69,11 +76,6 @@ public:
 //	ConstTransitivePtr<CGameState> state; //don't touch it in client's code
 // public:
 // 	
-// 	ConstTransitivePtr<CHeroHandler> heroh;
-// 	ConstTransitivePtr<CCreatureHandler> creh;
-// 	ConstTransitivePtr<CSpellHandler> spellh;
-// 	ConstTransitivePtr<CObjectHandler> objh;
-// 	ConstTransitivePtr<CDefObjInfoHandler> dobjinfo;
 // 	ConstTransitivePtr<CGeneralTextHandler> generaltexth;
 
 

+ 18 - 17
client/CMT.cpp

@@ -128,10 +128,10 @@ void init()
 	//initializing audio
 	// Note: because of interface button range, volume can only be a
 	// multiple of 11, from 0 to 99.
-	CGI->soundh = new CSoundHandler;
-	CGI->soundh->init();
-	CGI->soundh->setVolume(GDefaultOptions.soundVolume);
-	CGI->musich = new CMusicHandler;
+	CCS->soundh = new CSoundHandler;
+	CCS->soundh->init();
+	CCS->soundh->setVolume(GDefaultOptions.soundVolume);
+	CCS->musich = new CMusicHandler;
 	//CGI->musich->init();
 	//CGI->musich->setVolume(GDefaultOptions.musicVolume);
 	tlog0<<"\tInitializing sound: "<<pomtime.getDif()<<std::endl;
@@ -139,14 +139,14 @@ void init()
 
 	initDLL(::console,logfile);
 	const_cast<CGameInfo*>(CGI)->setFromLib();
-	CGI->soundh->initCreaturesSounds(CGI->creh->creatures);
-	CGI->soundh->initSpellsSounds(CGI->spellh->spells);
+	CCS->soundh->initCreaturesSounds(CGI->creh->creatures);
+	CCS->soundh->initSpellsSounds(CGI->spellh->spells);
 	tlog0<<"Initializing VCMI_Lib: "<<tmh.getDif()<<std::endl;
 
 	pomtime.getDif();
-	CGI->curh = new CCursorHandler;
-	CGI->curh->initCursor();
-	CGI->curh->show();
+	CCS->curh = new CCursorHandler;
+	CCS->curh->initCursor();
+	CCS->curh->show();
 	tlog0<<"Screen handler: "<<pomtime.getDif()<<std::endl;
 	pomtime.getDif();
 	graphics = new Graphics();
@@ -247,8 +247,9 @@ int main(int argc, char** argv)
 	tlog0 << NAME << std::endl;
 
 	srand ( time(NULL) );
-	//CPG=NULL;
-	CGI = new CGameInfo; //contains all global informations about game (texts, lodHandlers, map handler itp.)
+	
+	CCS = new CClientState;
+	CGI = new CGameInfo; //contains all global informations about game (texts, lodHandlers, map handler etc.)
 
 	if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO))
 	{
@@ -261,7 +262,7 @@ int main(int argc, char** argv)
 	tlog0 <<"\tInitializing screen: "<<pomtime.getDif() << std::endl;
 
 	// Initialize video
-	CGI->videoh = new CVideoPlayer;
+	CCS->videoh = new CVideoPlayer;
 	tlog0<<"\tInitializing video: "<<pomtime.getDif()<<std::endl;
 
 	//we can properly play intro only in the main thread, so we have to move loading to the separate thread
@@ -272,7 +273,7 @@ int main(int argc, char** argv)
 	loading.join();
 	tlog0<<"Initialization of VCMI (together): "<<total.getDif()<<std::endl;
 
-	CGI->musich->playMusic(musicBase::mainMenu, -1);
+	CCS->musich->playMusic(musicBase::mainMenu, -1);
 
 	GH.curInt = new CGPreGame; //will set CGP pointer to itself
 	mainGUIThread = new boost::thread(&CGuiHandler::run, boost::ref(GH));
@@ -474,9 +475,9 @@ void processCommand(const std::string &message)
 //plays intro, ends when intro is over or button has been pressed (handles events)
 void playIntro()
 {
-	if(CGI->videoh->openAndPlayVideo("3DOLOGO.SMK", 60, 40, screen, true))
+	if(CCS->videoh->openAndPlayVideo("3DOLOGO.SMK", 60, 40, screen, true))
 	{
-		CGI->videoh->openAndPlayVideo("AZVS.SMK", 60, 80, screen, true);
+		CCS->videoh->openAndPlayVideo("AZVS.SMK", 60, 80, screen, true);
 	}
 }
 
@@ -611,7 +612,7 @@ static void listenForEvents()
 
 				delete CGI->dobjinfo;
 				const_cast<CGameInfo*>(CGI)->dobjinfo = new CDefObjInfoHandler;
-				CGI->dobjinfo->load();
+				const_cast<CGameInfo*>(CGI)->dobjinfo->load();
 
 				GH.curInt = CGP;
 				GH.defActionsDef = 63;
@@ -675,7 +676,7 @@ void startGame(StartInfo * options, CConnection *serv/* = NULL*/)
 		break;
 	}
 
-	CGI->musich->stopMusic();
+	CCS->musich->stopMusic();
 	client->connectionHandler = new boost::thread(&CClient::run, client);
 }
 

+ 21 - 21
client/CPlayerInterface.cpp

@@ -446,7 +446,7 @@ void CPlayerInterface::receivedResource(int type, int val)
 void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16>& skills, boost::function<void(ui32)> &callback)
 {
 	waitWhileDialog();
-	CGI->soundh->playSound(soundBase::heroNewLevel);
+	CCS->soundh->playSound(soundBase::heroNewLevel);
 
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	CLevelWindow *lw = new CLevelWindow(hero,pskill,skills,callback);
@@ -530,7 +530,7 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID,
 	switch(what)
 	{
 	case 1:
-		CGI->soundh->playSound(soundBase::newBuilding);
+		CCS->soundh->playSound(soundBase::newBuilding);
 		castleInt->addBuilding(buildingID);
 		break;
 	case 2:
@@ -550,7 +550,7 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
 		SDL_Delay(20);
 
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
-	CGI->musich->playMusicFromSet(CGI->musich->battleMusics, -1);
+	CCS->musich->playMusicFromSet(CCS->musich->battleMusics, -1);
 	GH.pushInt(battleInt);
 }
 
@@ -839,7 +839,7 @@ void CPlayerInterface::showComp(SComponent comp)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 
-	CGI->soundh->playSoundFromSet(CGI->soundh->pickupSounds);
+	CCS->soundh->playSoundFromSet(CCS->soundh->pickupSounds);
 
 	adventureInt->infoBar.showComp(&comp,4000);
 }
@@ -862,7 +862,7 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
 	temp->setDelComps(delComps);
 	if(makingTurn && GH.listInt.size() && LOCPLINT == this)
 	{
-		CGI->soundh->playSound(static_cast<soundBase::soundID>(soundID));
+		CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
 		showingDialog->set(true);
 		GH.pushInt(temp);
 	}
@@ -887,7 +887,7 @@ void CPlayerInterface::showBlockingDialog( const std::string &text, const std::v
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	
 	stopMovement();
-	CGI->soundh->playSound(static_cast<soundBase::soundID>(soundID));
+	CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
 
 	if(!selection && cancel) //simple yes/no dialog
 	{
@@ -1067,14 +1067,14 @@ bool CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
 #if 0
 			// TODO
 			if (hero is flying && sh == -1)
-				sh = CGI->soundh->playSound(soundBase::horseFlying, -1);
+				sh = CCS->soundh->playSound(soundBase::horseFlying, -1);
 #endif
 			{
 				newTerrain = cb->getTileInfo(CGHeroInstance::convertPosition(path.nodes[i].coord, false))->tertype;
 
 				if (newTerrain != currentTerrain) {
-					CGI->soundh->stopSound(sh);
-					sh = CGI->soundh->playSound(CGI->soundh->horseSounds[newTerrain], -1);
+					CCS->soundh->stopSound(sh);
+					sh = CCS->soundh->playSound(CCS->soundh->horseSounds[newTerrain], -1);
 					currentTerrain = newTerrain;
 				}
 			}
@@ -1095,7 +1095,7 @@ bool CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
 				break;
 		}
 
-		CGI->soundh->stopSound(sh);
+		CCS->soundh->stopSound(sh);
 		cb->recalculatePaths();
 	}
 
@@ -1265,7 +1265,7 @@ void CPlayerInterface::newObject( const CGObjectInstance * obj )
 		&& LOCPLINT->castleInt
 		&&  obj->pos-obj->getVisitableOffset() == LOCPLINT->castleInt->town->bestLocation())
 	{
-		CGI->soundh->playSound(soundBase::newBuilding);
+		CCS->soundh->playSound(soundBase::newBuilding);
 		LOCPLINT->castleInt->recreateBuildings();
 	}
 }
@@ -1329,9 +1329,9 @@ void CPlayerInterface::update()
 	else
 		GH.simpleRedraw();
 
-	CGI->curh->draw1();
+	CCS->curh->draw1();
 	CSDL_Ext::update(screen);
-	CGI->curh->draw2();
+	CCS->curh->draw2();
 
 	screenLTmax = Point(conf.cc.resx - screen->w, conf.cc.resy - screen->h);
 
@@ -1862,14 +1862,14 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
 void SystemOptions::setMusicVolume( int newVolume )
 {
 	musicVolume = newVolume;
-	CGI->musich->setVolume(newVolume);
+	CCS->musich->setVolume(newVolume);
 	settingsChanged();
 }
 
 void SystemOptions::setSoundVolume( int newVolume )
 {
 	soundVolume = newVolume;
-	CGI->soundh->setVolume(newVolume);
+	CCS->soundh->setVolume(newVolume);
 	settingsChanged();
 }
 
@@ -1897,10 +1897,10 @@ void SystemOptions::settingsChanged()
 
 void SystemOptions::apply()
 {
-	if(CGI->musich->getVolume() != musicVolume)
-		CGI->musich->setVolume(musicVolume);
-	if(CGI->soundh->getVolume() != soundVolume)
-		CGI->soundh->setVolume(soundVolume);
+	if(CCS->musich->getVolume() != musicVolume)
+		CCS->musich->setVolume(musicVolume);
+	if(CCS->soundh->getVolume() != soundVolume)
+		CCS->soundh->setVolume(soundVolume);
 
 	settingsChanged();
 }
@@ -1980,9 +1980,9 @@ void CPlayerInterface::acceptTurn()
 	 * NEWDAY. And we don't play NEWMONTH. */
 	int day = cb->getDate(1);
 	if (day != 1)
-		CGI->soundh->playSound(soundBase::newDay);
+		CCS->soundh->playSound(soundBase::newDay);
 	else
-		CGI->soundh->playSound(soundBase::newWeek);
+		CCS->soundh->playSound(soundBase::newWeek);
 
 	adventureInt->infoBar.newDay(day);
 

+ 7 - 7
client/CPreGame.cpp

@@ -271,7 +271,7 @@ void CMenuScreen::showAll( SDL_Surface * to )
 void CMenuScreen::show( SDL_Surface * to )
 {
 	CIntObject::show(to);
-	CGI->videoh->update(pos.x + 8, pos.y + 105, screen, true, false);
+	CCS->videoh->update(pos.x + 8, pos.y + 105, screen, true, false);
 }
 
 void CMenuScreen::moveTo( CMenuScreen *next )
@@ -329,9 +329,9 @@ void CGPreGame::update()
 	if (GH.listInt.size() == 0)
 	{
 	#ifdef _WIN32
-		CGI->videoh->open("ACREDIT.SMK");
+		CCS->videoh->open("ACREDIT.SMK");
 	#else
-		CGI->videoh->open("ACREDIT.SMK", true, false);
+		CCS->videoh->open("ACREDIT.SMK", true, false);
 	#endif
 		GH.pushInt(scrs[CMenuScreen::mainMenu]);
 	}
@@ -339,9 +339,9 @@ void CGPreGame::update()
 	if(SEL)
 		SEL->update();
 
-	CGI->curh->draw1();
+	CCS->curh->draw1();
 	SDL_Flip(screen);
-	CGI->curh->draw2();
+	CCS->curh->draw2();
 	screenLTmax = Point(800 - screen->w, 600 - screen->h);
 	GH.topInt()->show(screen);
 	GH.updateTime();
@@ -2858,7 +2858,7 @@ void CBonusSelection::updateBonusSelection()
 			case 0: //spell
 				surfToDuplicate = de->ourImages[bonDescs[i].info2].bitmap;
 				desc = CGI->generaltexth->allTexts[715];
-				boost::algorithm::replace_first(desc, "%s", CGI->spellh->spells[bonDescs[i].info2].name);
+				boost::algorithm::replace_first(desc, "%s", CGI->spellh->spells[bonDescs[i].info2]->name);
 				break;
 			case 1: //monster
 				surfToDuplicate = de->ourImages[bonDescs[i].info2 + 2].bitmap;
@@ -2895,7 +2895,7 @@ void CBonusSelection::updateBonusSelection()
 			case 4: //spell scroll
 				surfToDuplicate = de->ourImages[bonDescs[i].info2].bitmap;
 				desc = CGI->generaltexth->allTexts[716];
-				boost::algorithm::replace_first(desc, "%s", CGI->spellh->spells[bonDescs[i].info2].name);
+				boost::algorithm::replace_first(desc, "%s", CGI->spellh->spells[bonDescs[i].info2]->name);
 				break;
 			case 5: //primary skill
 				{

+ 19 - 19
client/CSpellWindow.cpp

@@ -79,7 +79,7 @@ CSpellWindow::CSpellWindow(const SDL_Rect & myRect, const CGHeroInstance * _myHe
 	//initializing castable spells
 	for(ui32 v=0; v<CGI->spellh->spells.size(); ++v)
 	{
-		if( !CGI->spellh->spells[v].creatureAbility && myHero->canCastThisSpell(&CGI->spellh->spells[v]) )
+		if( !CGI->spellh->spells[v]->creatureAbility && myHero->canCastThisSpell(CGI->spellh->spells[v]) )
 			mySpells.insert(v);
 	}
 
@@ -91,7 +91,7 @@ CSpellWindow::CSpellWindow(const SDL_Rect & myRect, const CGHeroInstance * _myHe
 
 	for(std::set<ui32>::const_iterator g = mySpells.begin(); g!=mySpells.end(); ++g)
 	{
-		const CSpell &s = CGI->spellh->spells[*g];
+		const CSpell &s = *CGI->spellh->spells[*g];
 		Uint8 *sitesPerOurTab = s.combatSpell ? sitesPerTabBattle : sitesPerTabAdv;
 
 		++sitesPerOurTab[4];
@@ -355,8 +355,8 @@ class SpellbookSpellSorter
 public:
 	bool operator()(const int & a, const int & b)
 	{
-		CSpell A = CGI->spellh->spells[a];
-		CSpell B = CGI->spellh->spells[b];
+		const CSpell & A = *CGI->spellh->spells[a];
+		const CSpell & B = *CGI->spellh->spells[b];
 		if(A.level<B.level)
 			return true;
 		if(A.level>B.level)
@@ -386,11 +386,11 @@ void CSpellWindow::computeSpellsPerArea()
 	std::vector<ui32> spellsCurSite;
 	for(std::set<ui32>::const_iterator it = mySpells.begin(); it != mySpells.end(); ++it)
 	{
-		if(CGI->spellh->spells[*it].combatSpell ^ !battleSpellsOnly
-			&& ((CGI->spellh->spells[*it].air && selectedTab == 0) || 
-				(CGI->spellh->spells[*it].fire && selectedTab == 1) ||
-				(CGI->spellh->spells[*it].water && selectedTab == 2) ||
-				(CGI->spellh->spells[*it].earth && selectedTab == 3) ||
+		if(CGI->spellh->spells[*it]->combatSpell ^ !battleSpellsOnly
+			&& ((CGI->spellh->spells[*it]->air && selectedTab == 0) || 
+				(CGI->spellh->spells[*it]->fire && selectedTab == 1) ||
+				(CGI->spellh->spells[*it]->water && selectedTab == 2) ||
+				(CGI->spellh->spells[*it]->earth && selectedTab == 3) ||
 				selectedTab == 4 )
 			)
 		{
@@ -505,12 +505,12 @@ void CSpellWindow::deactivate()
 
 void CSpellWindow::turnPageLeft()
 {
-	CGI->videoh->openAndPlayVideo("PGTRNLFT.SMK", pos.x+13, pos.y+15, screen);
+	CCS->videoh->openAndPlayVideo("PGTRNLFT.SMK", pos.x+13, pos.y+15, screen);
 }
 
 void CSpellWindow::turnPageRight()
 {
-	CGI->videoh->openAndPlayVideo("PGTRNRGH.SMK", pos.x+13, pos.y+15, screen);
+	CCS->videoh->openAndPlayVideo("PGTRNRGH.SMK", pos.x+13, pos.y+15, screen);
 }
 
 void CSpellWindow::keyPressed(const SDL_KeyboardEvent & key)
@@ -594,7 +594,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
 {
 	if(!down && mySpell!=-1)
 	{
-		const CSpell *sp = &CGI->spellh->spells[mySpell];
+		const CSpell *sp = CGI->spellh->spells[mySpell];
 
 		int spellCost = owner->myInt->cb->getSpellCost(sp, owner->myHero);
 		if(spellCost > owner->myHero->mana) //insufficient mana
@@ -664,7 +664,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
 						}
 					}
 
-					if (h->getSpellSchoolLevel(&CGI->spellh->spells[spell]) < 3) //not expert - teleport to nearest available city
+					if (h->getSpellSchoolLevel(CGI->spellh->spells[spell]) < 3) //not expert - teleport to nearest available city
 					{
 						int nearest = -1; //nearest town's ID
 						double dist = -1;
@@ -710,7 +710,7 @@ void CSpellWindow::SpellArea::clickRight(tribool down, bool previousState)
 	{
 		std::string dmgInfo;
 		const CGHeroInstance * hero = owner->myHero;
-		int causedDmg = owner->myInt->cb->estimateSpellDamage( &CGI->spellh->spells[mySpell], (hero ? hero : NULL));
+		int causedDmg = owner->myInt->cb->estimateSpellDamage( CGI->spellh->spells[mySpell], (hero ? hero : NULL));
 		if(causedDmg == 0)
 			dmgInfo = "";
 		else
@@ -721,8 +721,8 @@ void CSpellWindow::SpellArea::clickRight(tribool down, bool previousState)
 
 		SDL_Surface *spellBox = CMessage::drawBoxTextBitmapSub(
 			owner->myInt->playerID,
-			CGI->spellh->spells[mySpell].descriptions[schoolLevel] + dmgInfo, this->owner->spells->ourImages[mySpell].bitmap,
-			CGI->spellh->spells[mySpell].name,30,30);
+			CGI->spellh->spells[mySpell]->descriptions[schoolLevel] + dmgInfo, this->owner->spells->ourImages[mySpell].bitmap,
+			CGI->spellh->spells[mySpell]->name,30,30);
 		CInfoPopup *vinya = new CInfoPopup(spellBox, true);
 		GH.pushInt(vinya);
 	}
@@ -736,7 +736,7 @@ void CSpellWindow::SpellArea::hover(bool on)
 		if(on)
 		{
 			std::ostringstream ss;
-			ss<<CGI->spellh->spells[mySpell].name<<" ("<<CGI->generaltexth->allTexts[171+CGI->spellh->spells[mySpell].level]<<")";
+			ss<<CGI->spellh->spells[mySpell]->name<<" ("<<CGI->generaltexth->allTexts[171+CGI->spellh->spells[mySpell]->level]<<")";
 			owner->statusBar->print(ss.str());
 		}
 		else
@@ -751,7 +751,7 @@ void CSpellWindow::SpellArea::showAll(SDL_Surface *to)
 	if(mySpell < 0)
 		return;
 
-	const CSpell * spell = &CGI->spellh->spells[mySpell];
+	const CSpell * spell = CGI->spellh->spells[mySpell];
 
 	blitAt(owner->spells->ourImages[mySpell].bitmap, pos.x, pos.y, to);
 	blitAt(owner->schoolBorders[owner->selectedTab >= 4 ? whichSchool : owner->selectedTab]->ourImages[schoolLevel].bitmap, pos.x, pos.y, to); //printing border (indicates level of magic school)
@@ -784,7 +784,7 @@ void CSpellWindow::SpellArea::setSpell(int spellID)
 	if(mySpell < 0)
 		return;
 
-	const CSpell * spell = &CGI->spellh->spells[mySpell];
+	const CSpell * spell = CGI->spellh->spells[mySpell];
 	schoolLevel = owner->myHero->getSpellSchoolLevel(spell, &whichSchool);
 	spellCost = owner->myInt->cb->getSpellCost(spell, owner->myHero);
 }

+ 1 - 1
client/GUIBase.cpp

@@ -188,7 +188,7 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
 	}
 	else if(sEvent->type==SDL_MOUSEMOTION)
 	{
-		CGI->curh->cursorMove(sEvent->motion.x, sEvent->motion.y);
+		CCS->curh->cursorMove(sEvent->motion.x, sEvent->motion.y);
 		HLP::adjustMousePos(sEvent);
 		handleMouseMotion(sEvent);
 	}

+ 21 - 21
client/GUIClasses.cpp

@@ -653,7 +653,7 @@ CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, const Point &p, EAlignment alignmen
 
 CInfoPopup::CInfoPopup(SDL_Surface *Bitmap, bool Free)
 {
-	CGI->curh->hide();
+	CCS->curh->hide();
 
 	free=Free;
 	bitmap=Bitmap;
@@ -679,12 +679,12 @@ void CInfoPopup::show(SDL_Surface * to)
 }
 CInfoPopup::~CInfoPopup()
 {
-	CGI->curh->show();
+	CCS->curh->show();
 }
 
 void CInfoPopup::init(int x, int y)
 {
-	CGI->curh->hide();
+	CCS->curh->hide();
 
 	pos.x = x;
 	pos.y = y;
@@ -745,8 +745,8 @@ void SComponent::init(Etype Type, int Subtype, int Val)
 		subtitle = oss.str();
 		break;
 	case spell:
-		description = CGI->spellh->spells[Subtype].descriptions[Val];
-		subtitle = CGI->spellh->spells[Subtype].name;
+		description = CGI->spellh->spells[Subtype]->descriptions[Val];
+		subtitle = CGI->spellh->spells[Subtype]->name;
 		break;
 	case creature:
 		subtitle = (Val? boost::lexical_cast<std::string>(Val) + " " : "") + CGI->creh->creatures[Subtype]->*(Val != 1 ? &CCreature::namePl : &CCreature::nameSing);
@@ -1899,7 +1899,7 @@ void CRecruitmentWindow::initCres()
 
 			cur.amount = dwelling->creatures[i].first;
 			cur.ID = dwelling->creatures[i].second[j];
-			CCreature * cre= CGI->creh->creatures[cur.ID];
+			const CCreature * cre= CGI->creh->creatures[cur.ID];
 
 			for(int k=0; k<cre->cost.size(); k++)
 				if(cre->cost[k])
@@ -2638,7 +2638,7 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
 				aw->arts->commonInfo->srcSlotID = 19 + vstd::findPos(aw->hero->artifacts, const_cast<CArtifact*>(movedArt));
 
 				aw->arts->commonInfo->destAOH = aw->arts;
-				CGI->curh->dragAndDropCursor(graphics->artDefs->ourImages[movedArt->id].bitmap);
+				CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[movedArt->id].bitmap);
 
 				id = -1;
 				subtitle = "";
@@ -3909,7 +3909,7 @@ CSystemOptionsWindow::CSystemOptionsWindow(const SDL_Rect &pos, CPlayerInterface
 	{
 		musicVolume->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[326+i].second),CGI->generaltexth->zelp[326+i].second, "syslb.def", pos.x+29 + 19*i, pos.y+359, i*11);
 	}
-	musicVolume->select(CGI->musich->getVolume(), 1);
+	musicVolume->select(CCS->musich->getVolume(), 1);
 	musicVolume->onChange = boost::bind(&SystemOptions::setMusicVolume, &owner->sysOpts, _1);
 
 	effectsVolume = new CHighlightableButtonsGroup(0, true);
@@ -3917,7 +3917,7 @@ CSystemOptionsWindow::CSystemOptionsWindow(const SDL_Rect &pos, CPlayerInterface
 	{
 		effectsVolume->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[336+i].second),CGI->generaltexth->zelp[336+i].second, "syslb.def", pos.x+29 + 19*i, pos.y+425, i*11);
 	}
-	effectsVolume->select(CGI->soundh->getVolume(), 1);
+	effectsVolume->select(CCS->soundh->getVolume(), 1);
 	effectsVolume->onChange = boost::bind(&SystemOptions::setSoundVolume, &owner->sysOpts, _1);
 }
 
@@ -4065,9 +4065,9 @@ CTavernWindow::CTavernWindow(const CGObjectInstance *TavernObj)
 	}
 
 #ifdef _WIN32
-	CGI->videoh->open("TAVERN.BIK");
+	CCS->videoh->open("TAVERN.BIK");
 #else
-	CGI->videoh->open("tavern.mjpg", true, false);
+	CCS->videoh->open("tavern.mjpg", true, false);
 #endif
 }
 
@@ -4086,7 +4086,7 @@ void CTavernWindow::thievesguildb()
 
 CTavernWindow::~CTavernWindow()
 {
-	CGI->videoh->close();
+	CCS->videoh->close();
 }
 
 void CTavernWindow::close()
@@ -4098,7 +4098,7 @@ void CTavernWindow::show(SDL_Surface * to)
 {
 	CIntObject::show(to);
 
-	CGI->videoh->update(pos.x+70, pos.y+56, to, true, false);
+	CCS->videoh->update(pos.x+70, pos.y+56, to, true, false);
 	if(selected >= 0)
 	{
 		HeroPortrait *sel = selected ? h2 : h1;
@@ -4473,7 +4473,7 @@ void CRClickPopupInt::show(SDL_Surface * to)
 
 CRClickPopupInt::CRClickPopupInt( IShowActivable *our, bool deleteInt )
 {
-	CGI->curh->hide();
+	CCS->curh->hide();
 	inner = our;
 	delInner = deleteInt;
 }
@@ -4488,7 +4488,7 @@ CRClickPopupInt::~CRClickPopupInt()
 	if(delInner)
 		delete inner;
 
-	CGI->curh->show();
+	CCS->curh->show();
 }
 
 CArtPlace::CArtPlace(const CArtifact* Art)
@@ -4671,7 +4671,7 @@ void CArtPlace::select ()
 
 	int backpackCorrection = -(slotID - 19 < ourOwner->backpackPos);
 
-	CGI->curh->dragAndDropCursor(graphics->artDefs->ourImages[ourArt->id].bitmap);
+	CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[ourArt->id].bitmap);
 
 	ourOwner->commonInfo->srcArtifact = ourArt;
 	ourOwner->commonInfo->srcSlotID = slotID;
@@ -4701,7 +4701,7 @@ void CArtPlace::select ()
  */
 void CArtPlace::deselect ()
 {
-	CGI->curh->dragAndDropCursor(NULL);
+	CCS->curh->dragAndDropCursor(NULL);
 	ourOwner->unmarkSlots();
 }
 
@@ -4886,7 +4886,7 @@ void CArtifactsOfHero::SCommonPart::reset()
 	destAOH = srcAOH = NULL;
 	destArtifact = srcArtifact = NULL;
 	destSlotID = srcSlotID = -1;
-	CGI->curh->dragAndDropCursor(NULL);
+	CCS->curh->dragAndDropCursor(NULL);
 }
 
 void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
@@ -4928,7 +4928,7 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
 				commonInfo->destArtifact = NULL;
 				commonInfo->destSlotID = -1;
 
-				CGI->curh->dragAndDropCursor(graphics->artDefs->ourImages[commonInfo->srcArtifact->id].bitmap);
+				CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[commonInfo->srcArtifact->id].bitmap);
 				markPossibleSlots(commonInfo->srcArtifact);
 			} 
 			else if (commonInfo->destAOH != NULL) 
@@ -4965,7 +4965,7 @@ void CArtifactsOfHero::dispose()
 {
 	//delNull(curHero);
 	unmarkSlots(false);
-	CGI->curh->dragAndDropCursor(NULL);
+	CCS->curh->dragAndDropCursor(NULL);
 }
 
 void CArtifactsOfHero::scrollBackpack(int dir)
@@ -5317,7 +5317,7 @@ void CExchangeWindow::show(SDL_Surface * to)
 
 void CExchangeWindow::questlog(int whichHero)
 {
-	CGI->curh->dragAndDropCursor(NULL);
+	CCS->curh->dragAndDropCursor(NULL);
 }
 
 void CExchangeWindow::prepareBackground()

+ 1 - 1
client/GUIClasses.h

@@ -1051,7 +1051,7 @@ private:
 	AdventureMapButton * quitb;
 	CResDataBar * resdatabar;
 
-	std::vector<std::pair<SDL_Surface *, SPuzzleInfo *> > puzzlesToPullBack;
+	std::vector<std::pair<SDL_Surface *, const SPuzzleInfo *> > puzzlesToPullBack;
 	ui8 animCount;
 
 public:

+ 12 - 0
client/Graphics.cpp

@@ -20,6 +20,8 @@
 #include "../hch/CGeneralTextHandler.h"
 #include "../hch/CCreatureHandler.h"
 #include "CBitmapHandler.h"
+#include "../hch/CObjectHandler.h"
+#include "../hch/CDefObjInfoHandler.h"
 
 using namespace boost::assign;
 using namespace CSDL_Ext;
@@ -720,6 +722,16 @@ void Graphics::loadFonts()
 		fonts[i] = loadFont(fontnames[i]);
 }
 
+CDefEssential * Graphics::getDef( const CGObjectInstance * obj )
+{
+	return advmapobjGraphics[obj->defInfo->id][obj->defInfo->subid];
+}
+
+CDefEssential * Graphics::getDef( const CGDefInfo * info )
+{
+	return advmapobjGraphics[info->id][info->subid];
+}
+
 Font::Font(unsigned char *Data)
 {
 	data = Data;

+ 7 - 0
client/Graphics.h

@@ -24,6 +24,9 @@ class CHeroClass;
 struct SDL_Color;
 struct InfoAboutHero;
 struct InfoAboutTown;
+class CGObjectInstance;
+class CGDefInfo;
+
 typedef struct _TTF_Font TTF_Font; //from SDL_ttf.h
 
 class Graphics
@@ -62,6 +65,10 @@ public:
 	std::map<std::string, CDefEssential*> mapObjectDefs; //pointers to loaded defs (key is filename, uppercase)
 	CDefHandler * FoWfullHide; //for Fog of War
 	CDefHandler * FoWpartialHide; //for For of War
+
+	std::map<int, std::map<int, CDefEssential *> > advmapobjGraphics;
+	CDefEssential * getDef(const CGObjectInstance * obj);
+	CDefEssential * getDef(const CGDefInfo * info);
 	//creatures
 	std::map<int,SDL_Surface*> smallImgs; //creature ID -> small 32x32 img of creature; //ID=-2 is for blank (black) img; -1 for the border
 	std::map<int,SDL_Surface*> bigImgs; //creature ID -> big 58x64 img of creature; //ID=-2 is for blank (black) img; -1 for the border

+ 25 - 29
client/mapHandler.cpp

@@ -249,12 +249,12 @@ void CMapHandler::initObjectRects()
 			|| obj->ID==HEROI_TYPE && static_cast<const CGHeroInstance*>(obj)->inTownGarrison //garrisoned hero
 			|| obj->ID==8 && static_cast<const CGBoat*>(obj)->hero //boat wih hero (hero graphics is used)
 			|| !obj->defInfo
-			|| !obj->defInfo->handler) //no graphic...
+			|| !graphics->getDef(obj)) //no graphic...
 		{
 			continue;
 		}
 
-		const SDL_Surface *bitmap = obj->defInfo->handler->ourImages[0].bitmap;
+		const SDL_Surface *bitmap = graphics->getDef(obj)->ourImages[0].bitmap;
 		for(int fx=0; fx<bitmap->w>>5; ++fx) //bitmap->w/32
 		{
 			for(int fy=0; fy<bitmap->h>>5; ++fy) //bitmap->h/32
@@ -297,25 +297,29 @@ void CMapHandler::initObjectRects()
 static void processDef (CGDefInfo* def)
 {
 	if(def->id == EVENTI_TYPE)
+	{
+		graphics->advmapobjGraphics[def->id][def->subid] = NULL;
 		return;
+	}
 
-	if(!def->handler) //if object has already set handler (eg. heroes) it should not be overwritten
+	CDefEssential * ourDef = graphics->getDef(def);
+
+	if(!ourDef) //if object has already set handler (eg. heroes) it should not be overwritten
 	{
 		if(def->name.size())
 		{
 			if(vstd::contains(graphics->mapObjectDefs, def->name))
 			{
-				def->handler = graphics->mapObjectDefs[def->name];
+				graphics->advmapobjGraphics[def->id][def->subid] = graphics->mapObjectDefs[def->name];
 			}
 			else
 			{
-				graphics->mapObjectDefs[def->name] = def->handler = CDefHandler::giveDefEss(def->name);
+				graphics->mapObjectDefs[def->name] = graphics->advmapobjGraphics[def->id][def->subid] = CDefHandler::giveDefEss(def->name);
 			}
 		}
 		else
 		{
 			tlog2 << "No def name for " << def->id << "  " << def->subid << std::endl;
-			def->handler = NULL;
 			return;
 		}
 
@@ -323,36 +327,28 @@ static void processDef (CGDefInfo* def)
 // 		def->height = def->handler->ourImages[0].bitmap->h/32;
 	}
 
-	CGDefInfo* pom = CGI->dobjinfo->gobjs[def->id][def->subid];
-	if(pom && def->id!=TOWNI_TYPE)
-	{
-		pom->handler = def->handler;
-		pom->width = pom->handler->ourImages[0].bitmap->w/32;
-		pom->height = pom->handler->ourImages[0].bitmap->h/32;
-	}
-	else if(def->id != HEROI_TYPE && def->id != TOWNI_TYPE)
-		tlog3 << "\t\tMinor warning: lacking def info for " << def->id << " " << def->subid <<" " << def->name << std::endl;
-
+	ourDef = graphics->getDef(def);
+	
 	//alpha transformation
-	for(size_t yy=0; yy < def->handler->ourImages.size(); ++yy)
+	for(size_t yy=0; yy < ourDef->ourImages.size(); ++yy)
 	{
-		CSDL_Ext::alphaTransform(def->handler->ourImages[yy].bitmap);
+		CSDL_Ext::alphaTransform(ourDef->ourImages[yy].bitmap);
 	}
 }
 void CMapHandler::initHeroDef(CGHeroInstance * h)
 {
-	h->defInfo->handler = graphics->flags1[0];
-	h->defInfo->width = h->defInfo->handler->ourImages[0].bitmap->w/32;
-	h->defInfo->height = h->defInfo->handler->ourImages[0].bitmap->h/32;
+	graphics->advmapobjGraphics[h->defInfo->id][h->defInfo->subid] = graphics->flags1[0];
+	h->defInfo->width =graphics->getDef(h)->ourImages[0].bitmap->w/32;
+	h->defInfo->height = graphics->getDef(h)->ourImages[0].bitmap->h/32;
 }
 void CMapHandler::init()
 {
 	timeHandler th;
 	th.getDif();
 
-	CGI->dobjinfo->gobjs[8][0]->handler = graphics->boatAnims[0];
-	CGI->dobjinfo->gobjs[8][1]->handler = graphics->boatAnims[1];
-	CGI->dobjinfo->gobjs[8][2]->handler = graphics->boatAnims[2];
+	graphics->advmapobjGraphics[8][0] = graphics->boatAnims[0];
+	graphics->advmapobjGraphics[8][1] = graphics->boatAnims[1];
+	graphics->advmapobjGraphics[8][2] = graphics->boatAnims[2];
 
 	// Size of visible terrain.
 	int mapW = conf.go()->ac.advmapW;
@@ -385,7 +381,7 @@ void CMapHandler::init()
 
 	for(int i=0;i<map->heroes.size();i++)
 	{
-		if(!map->heroes[i]->defInfo->handler)
+		if( !graphics->getDef(map->heroes[i]) )
 		{
 			initHeroDef(map->heroes[i]);
 		}
@@ -637,7 +633,7 @@ void CMapHandler::terrainRect(int3 top_tile, unsigned char anim,
 				}
 				else //blit normal object
 				{
-					const std::vector<Cimage> &ourImages = obj->defInfo->handler->ourImages;
+					const std::vector<Cimage> &ourImages = graphics->getDef(obj)->ourImages;
 					SDL_Surface *bitmap = ourImages[(anim+obj->animPhaseShift)%ourImages.size()].bitmap;
 
 					//setting appropriate flag color
@@ -824,10 +820,10 @@ std::pair<SDL_Surface *, bool> CMapHandler::getVisBitmap( const int3 & pos, cons
 
 bool CMapHandler::printObject(const CGObjectInstance *obj)
 {
-	if(!obj->defInfo->handler)
+	if(!graphics->getDef(obj))
 		processDef(obj->defInfo);
 
-	const SDL_Surface *bitmap = obj->defInfo->handler->ourImages[0].bitmap;
+	const SDL_Surface *bitmap = graphics->getDef(obj)->ourImages[0].bitmap;
 	const int tilesW = bitmap->w/32;
 	const int tilesH = bitmap->h/32;
 
@@ -868,7 +864,7 @@ bool CMapHandler::printObject(const CGObjectInstance *obj)
 
 bool CMapHandler::hideObject(const CGObjectInstance *obj)
 {
-	CDefEssential * curd = obj->defInfo->handler;
+	CDefEssential * curd = graphics->getDef(obj);
 	if(!curd) return false;
 	const SDL_Surface *bitmap = curd->ourImages[0].bitmap;
 	for(int fx=0; fx<bitmap->w/32; ++fx)

+ 3 - 1
global.h

@@ -79,6 +79,8 @@ enum ECombatInfo{ALIVE = 180, SUMMONED, CLONED, HAD_MORALE, WAITING, MOVED, DEFE
 
 class CGameInfo;
 extern const CGameInfo* CGI; //game info for general use
+class CClientState;
+extern CClientState * CCS;
 
 //a few typedefs for CCreatureSet
 typedef si32 TSlot;
@@ -176,7 +178,7 @@ class bmap : public std::map<KeyT, ValT>
 public:
 	const ValT & operator[](KeyT key) const
 	{
-		const_iterator it = find(*this, key);
+		const_iterator it = find(key);
 		return it->second;
 	}
 	ValT & operator[](KeyT key) 

+ 4 - 8
hch/CDefObjInfoHandler.cpp

@@ -30,7 +30,6 @@ bool CGDefInfo::isVisitable() const
 }
 CGDefInfo::CGDefInfo()
 {
-	handler = NULL;
 	visitDir = (8|16|32|64|128); //4,5,6,7,8 - any not-from-up direction
 
 	width = height = -1;
@@ -59,7 +58,6 @@ void CDefObjInfoHandler::load()
 	for(int hh=0; hh<objNumber; ++hh)
 	{
 		CGDefInfo* nobj = new CGDefInfo();
-		nobj->handler = NULL;
 		std::string dump;
 		inp>>nobj->name;
 		
@@ -132,19 +130,17 @@ void CDefObjInfoHandler::load()
 		static const char *holeDefs[] = {"AVLHOLD0.DEF", "AVLHLDS0.DEF", "AVLHOLG0.DEF", "AVLHLSN0.DEF",
 			"AVLHOLS0.DEF", "AVLHOLR0.DEF", "AVLHOLX0.DEF", "AVLHOLL0.DEF"};
 
-		CGDefInfo *& tmp = gobjs[124][i];
 		if(i)
 		{
-			tmp = new CGDefInfo;
-			*tmp = *gobjs[124][0];
+			gobjs[124][i] = new CGDefInfo(*gobjs[124][0]);
+			gobjs[124][i]->name = holeDefs[i];
 		}
-		tmp->name = holeDefs[i];
 	}
 }
  
 CDefObjInfoHandler::~CDefObjInfoHandler()
 {
-	for(std::map<int,std::map<int,CGDefInfo*> >::iterator i=gobjs.begin(); i!=gobjs.end(); i++)
-		for(std::map<int,CGDefInfo*>::iterator j=i->second.begin(); j!=i->second.end(); j++)
+	for(bmap<int,bmap<int, ConstTransitivePtr<CGDefInfo> > >::iterator i=gobjs.begin(); i!=gobjs.end(); i++)
+		for(bmap<int, ConstTransitivePtr<CGDefInfo> >::iterator j=i->second.begin(); j!=i->second.end(); j++)
 			delete j->second;
 }

+ 3 - 3
hch/CDefObjInfoHandler.h

@@ -3,6 +3,7 @@
 #include <vector>
 #include <map>
 #include "../global.h"
+#include "../lib/ConstTransitivePtr.h"
 
 /*
  * CDefObjInfoHandler.h, part of VCMI engine
@@ -30,7 +31,6 @@ public:
 		 terrainMenu; //in which menus in map editor object will be showed
 	si32 width, height; //tiles
 	si32 type; //(0- ground, 1- towns, 2-creatures, 3- heroes, 4-artifacts, 5- resources)   
-	CDefEssential * handler;
 	si32 printPriority;
 	bool isVisitable() const;
 	bool operator<(const CGDefInfo& por) const
@@ -51,8 +51,8 @@ void fetchInfoFromMSK();
 class DLL_EXPORT CDefObjInfoHandler
 {
 public:
-	std::map<int,std::map<int,CGDefInfo*> > gobjs;
-	std::map<int,CGDefInfo*> castles;
+	bmap<int, bmap<int, ConstTransitivePtr<CGDefInfo> > > gobjs;
+	bmap<int, ConstTransitivePtr<CGDefInfo> > castles;
 
 	void load();
 	~CDefObjInfoHandler();

+ 8 - 6
hch/CMusicHandler.cpp

@@ -29,7 +29,7 @@ static boost::bimap<soundBase::soundID, std::string> sounds;
 
 // Not pretty, but there's only one music handler object in the game.
 static void musicFinishedCallbackC(void) {
-	CGI->musich->musicFinishedCallback();
+	CCS->musich->musicFinishedCallback();
 }
 
 void CAudioBase::init()
@@ -148,7 +148,7 @@ soundBase::soundID CSoundHandler::getSoundID(std::string &fileName)
 		return it->second;
 }
 
-void CSoundHandler::initCreaturesSounds(std::vector<ConstTransitivePtr< CCreature> > &creatures)
+void CSoundHandler::initCreaturesSounds(const std::vector<ConstTransitivePtr< CCreature> > &creatures)
 {
 	tlog5 << "\t\tReading config/cr_sounds.txt" << std::endl;
 	std::ifstream ifs(DATA_DIR "/config/cr_sounds.txt");
@@ -222,7 +222,7 @@ void CSoundHandler::initCreaturesSounds(std::vector<ConstTransitivePtr< CCreatur
 	}*/
 }
 
-void CSoundHandler::initSpellsSounds(std::vector<CSpell> &spells)
+void CSoundHandler::initSpellsSounds(const std::vector< ConstTransitivePtr<CSpell> > &spells)
 {
 	tlog5 << "\t\tReading config/sp_sounds.txt" << std::endl;
 	std::ifstream ifs(DATA_DIR "/config/sp_sounds.txt");
@@ -238,12 +238,14 @@ void CSoundHandler::initSpellsSounds(std::vector<CSpell> &spells)
 
 		if (str.good() || (str.eof() && soundfile != ""))
 		{
-			const CSpell &s = CGI->spellh->spells[spellid];
+			const CSpell *s = CGI->spellh->spells[spellid];
 
-			if (s.soundID != soundBase::invalid)
+			if (vstd::contains(spellSounds, s))
+			{
 				tlog1 << "Spell << " << spellid << " already has a sound" << std::endl;
+			}
 			
-			s.soundID = getSoundID(soundfile);
+			spellSounds[s] = getSoundID(soundfile);
 		}
 	}
 	ifs.close();

+ 4 - 3
hch/CMusicHandler.h

@@ -80,8 +80,8 @@ public:
 	void init();
 	void release();
 
-	void initCreaturesSounds(std::vector<ConstTransitivePtr<CCreature> > &creatures);
-	void initSpellsSounds(std::vector<CSpell> &spells);
+	void initCreaturesSounds(const std::vector<ConstTransitivePtr<CCreature> > &creatures);
+	void initSpellsSounds(const std::vector< ConstTransitivePtr<CSpell> > &spells);
 	void setVolume(unsigned int percent);
 
 	// Sounds
@@ -89,6 +89,7 @@ public:
 	int playSoundFromSet(std::vector<soundBase::soundID> &sound_vec);
 	void stopSound(int handler);
 	std::vector <struct CreaturesBattleSounds> CBattleSounds;
+	std::map<const CSpell*, soundBase::soundID> spellSounds;
 
 	// Sets
 	std::vector<soundBase::soundID> pickupSounds;
@@ -96,7 +97,7 @@ public:
 };
 
 // Helper
-#define battle_sound(creature,what_sound) CGI->soundh->CBattleSounds[(creature)->idNumber].what_sound
+#define battle_sound(creature,what_sound) CCS->soundh->CBattleSounds[(creature)->idNumber].what_sound
 
 class CMusicHandler: public CAudioBase
 {

+ 4 - 5
hch/CObjectHandler.cpp

@@ -914,7 +914,6 @@ void CGHeroInstance::initHeroDefInfo()
 		defInfo->coverageMap[i] = 0;
 		defInfo->shadowCoverage[i] = 0;
 	}
-	defInfo->handler=NULL;
 	defInfo->blockMap[5] = 253;
 	defInfo->visitMap[5] = 2;
 	defInfo->coverageMap[4] = defInfo->coverageMap[5] = 224;
@@ -4915,10 +4914,10 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con
 	{
 		std::set<ui32> spellsToGive;
 		iw.components.clear();
-		std::vector<CSpell> * sp = &VLC->spellh->spells;
+		std::vector<ConstTransitivePtr<CSpell> > * sp = &VLC->spellh->spells;
 		for(std::vector<si32>::const_iterator i=spells.begin(); i != spells.end(); i++)
 		{
-			if ((*sp)[*i].level <= h->getSecSkillLevel(7) + 2) //enough wisdom
+			if ((*sp)[*i]->level <= h->getSecSkillLevel(7) + 2) //enough wisdom
 			{
 				iw.components.push_back(Component(Component::SPELL,*i,0,0));
 				spellsToGive.insert(*i);
@@ -5201,7 +5200,7 @@ const std::string & CGShrine::getHoverText() const
 	if(hasVisited(cb->getCurrentPlayer())) //TODO: use local player, not current
 	{
 		hoverName += "\n" + VLC->generaltexth->allTexts[355]; // + (learn %s)
-		boost::algorithm::replace_first(hoverName,"%s",VLC->spellh->spells[spell].name);
+		boost::algorithm::replace_first(hoverName,"%s",VLC->spellh->spells[spell]->name);
 		const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer());
 		if(h && vstd::contains(h->spells,spell)) //hero knows that ability
 			hoverName += "\n\n" + VLC->generaltexth->allTexts[354]; // (Already learned)
@@ -5247,7 +5246,7 @@ void CGScholar::onHeroVisit( const CGHeroInstance * h ) const
 	int ssl = h->getSecSkillLevel(bid); //current sec skill level, used if bonusType == 1
 	if((type == 1
 			&& ((ssl == 3)  ||  (!ssl  &&  h->secSkills.size() == SKILL_PER_HERO))) ////hero already has expert level in the skill or (don't know skill and doesn't have free slot)
-		|| (type == 2  &&  (!h->getArt(17) || vstd::contains(h->spells, (ui32) bid) || (VLC->spellh->spells[bid].level > h->getSecSkillLevel(7) + 2)
+		|| (type == 2  &&  (!h->getArt(17) || vstd::contains(h->spells, (ui32) bid) || (VLC->spellh->spells[bid]->level > h->getSecSkillLevel(7) + 2)
 		))) //hero doesn't have a spellbook or already knows the spell or doesn't have Wisdom
 	{
 		type = 0;

+ 2 - 2
hch/CObjectHandler.h

@@ -12,6 +12,7 @@
 #include "../lib/VCMI_Lib.h"
 #endif
 #include "../lib/CCreatureSet.h"
+#include "../lib/ConstTransitivePtr.h"
 
 /*
  * CObjectHandler.h, part of VCMI engine
@@ -1116,7 +1117,6 @@ public:
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & static_cast<CPlayersVisited&>(*this);
-		h & players;
 	}
 };
 
@@ -1229,7 +1229,7 @@ class DLL_EXPORT CObjectHandler
 {
 public:
 	std::vector<si32> cregens; //type 17. dwelling subid -> creature ID
-	std::map <ui32, std::vector <BankConfig*> > banksInfo; //[index][preset]
+	std::map <ui32, std::vector < ConstTransitivePtr<BankConfig> > > banksInfo; //[index][preset]
 	std::map <ui32, std::string> creBanksNames; //[crebank index] -> name of this creature bank
 	std::vector<ui32> resVals; //default values of resources in gold
 

+ 31 - 32
hch/CSpellHandler.cpp

@@ -217,10 +217,10 @@ void CSpellHandler::loadSpells()
 	{
 		if(spells.size()==81)
 			break;
-		CSpell nsp; //new currently being read spell
+		CSpell * nsp = new CSpell; //new currently being read spell
 
-		loadToIt(nsp.name,buf,i,4);
-		if(nsp.name == std::string(""))
+		loadToIt(nsp->name,buf,i,4);
+		if(nsp->name == std::string(""))
 		{
 			if(ifHit == 0)
 			{
@@ -232,50 +232,49 @@ void CSpellHandler::loadSpells()
 			}
 			for(int z=0; z<3; ++z)
 				loadToIt(pom,buf,i,3);
-			loadToIt(nsp.name,buf,i,4);
+			loadToIt(nsp->name,buf,i,4);
 			++ifHit;
 		}
 
-		loadToIt(nsp.abbName,buf,i,4);
-		loadToIt(nsp.level,buf,i,4);
+		loadToIt(nsp->abbName,buf,i,4);
+		loadToIt(nsp->level,buf,i,4);
 		loadToIt(pom,buf,i,4);
-		nsp.earth = startsWithX(pom);
+		nsp->earth = startsWithX(pom);
 		loadToIt(pom,buf,i,4);
-		nsp.water = startsWithX(pom);
+		nsp->water = startsWithX(pom);
 		loadToIt(pom,buf,i,4);
-		nsp.fire = startsWithX(pom);
+		nsp->fire = startsWithX(pom);
 		loadToIt(pom,buf,i,4);
-		nsp.air = startsWithX(pom);
+		nsp->air = startsWithX(pom);
 
-		nsp.costs.resize(4);
+		nsp->costs.resize(4);
 		for (int z = 0; z < 4 ; z++)
-			loadToIt(nsp.costs[z],buf,i,4);
-		loadToIt(nsp.power,buf,i,4);
-		nsp.powers.resize(4);
+			loadToIt(nsp->costs[z],buf,i,4);
+		loadToIt(nsp->power,buf,i,4);
+		nsp->powers.resize(4);
 		for (int z = 0; z < 4 ; z++)
-			loadToIt(nsp.powers[z],buf,i,4);
+			loadToIt(nsp->powers[z],buf,i,4);
 
-		nsp.probabilities.resize(9);
+		nsp->probabilities.resize(9);
 		for (int z = 0; z < 9 ; z++)
-			loadToIt(nsp.probabilities[z],buf,i,4);
+			loadToIt(nsp->probabilities[z],buf,i,4);
 
-		nsp.AIVals.resize(4);
+		nsp->AIVals.resize(4);
 		for (int z = 0; z < 4 ; z++)
-			loadToIt(nsp.AIVals[z],buf,i,4);
+			loadToIt(nsp->AIVals[z],buf,i,4);
 
-		nsp.descriptions.resize(4);
+		nsp->descriptions.resize(4);
 		for (int z = 0; z < 4 ; z++)
 		{
-			loadToIt(nsp.descriptions[z],buf,i,4);
-			boost::algorithm::replace_all(nsp.descriptions[z],"\"","");
+			loadToIt(nsp->descriptions[z],buf,i,4);
+			boost::algorithm::replace_all(nsp->descriptions[z],"\"","");
 		}
 
-		loadToIt(nsp.attributes,buf,i,3);
-		nsp.id = spells.size();
-		nsp.combatSpell = combSpells;
-		nsp.creatureAbility = creatureAbility;
-		nsp.mainEffectAnim = -1;
-		nsp.soundID = soundBase::invalid;
+		loadToIt(nsp->attributes,buf,i,3);
+		nsp->id = spells.size();
+		nsp->combatSpell = combSpells;
+		nsp->creatureAbility = creatureAbility;
+		nsp->mainEffectAnim = -1;
 		spells.push_back(nsp);
 	}
 	//loading of additional spell traits
@@ -297,13 +296,13 @@ void CSpellHandler::loadSpells()
 		{
 			int buf;
 			ast >> buf;
-			spells[spellID].positiveness = buf;
+			spells[spellID]->positiveness = buf;
 			ast >> buf;
-			spells[spellID].mainEffectAnim = buf;
+			spells[spellID]->mainEffectAnim = buf;
 
-			spells[spellID].range.resize(4);
+			spells[spellID]->range.resize(4);
 			for(int g=0; g<4; ++g)
-				ast>>spells[spellID].range[g];
+				ast>>spells[spellID]->range[g];
 			ast>>spellID;
 		}
 	}

+ 2 - 3
hch/CSpellHandler.h

@@ -5,7 +5,7 @@
 #include <vector>
 #include <set>
 
-#include "CSoundBase.h"
+#include "../lib/ConstTransitivePtr.h"
 
 /*
  * CSpellHandler.h, part of VCMI engine
@@ -41,7 +41,6 @@ public:
 	std::vector<std::string> range; //description of spell's range in SRSL by magic school level
 	std::set<ui16> rangeInHexes(unsigned int centralHex, ui8 schoolLvl ) const; //convert range to specific hexes
 	si16 mainEffectAnim; //main spell effect animation, in AC format (or -1 when none)
-	mutable soundBase::soundID soundID;	// spell sound id
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -61,7 +60,7 @@ class DLL_EXPORT CSpellHandler
 {
 public:
 	CSpellHandler();
-	std::vector<CSpell> spells;
+	std::vector< ConstTransitivePtr<CSpell> > spells;
 	void loadSpells();
 
 	template <typename Handler> void serialize(Handler &h, const int version)

+ 16 - 20
lib/CGameState.cpp

@@ -166,7 +166,7 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst
 	}
 	else if(type == SPELL_NAME)
 	{
-		dst = VLC->spellh->spells[ser].name;
+		dst = VLC->spellh->spells[ser]->name;
 	}
 	else if(type == CRE_SING_NAMES)
 	{
@@ -784,7 +784,7 @@ const Bonus * CStack::getEffect( ui16 id, int turn /*= 0*/ ) const
 
 void CStack::stackEffectToFeature(BonusList & sf, const Bonus & sse)
 {
-// 	si32 power = VLC->spellh->spells[sse.id].powers[sse.val];
+// 	si32 power = VLC->spellh->spells[sse.id]->powers[sse.val];
 // 	Bonus * bonus = getBonus(Selector::typeSybtype(Bonus::SPECIAL_PECULIAR_ENCHANT, sse.id));
 // 	if (bonus)
 // 	{
@@ -921,7 +921,7 @@ void CStack::stackEffectToFeature(BonusList & sf, const Bonus & sse)
 // 		sf.back().id = sse.id;
 // 		break;
 // 	case 56: //frenzy
-// 		sf.push_back(featureGenerator(Bonus::IN_FRENZY, 0, VLC->spellh->spells[56].powers[sse.val]/100.0, sse.turnsRemain));
+// 		sf.push_back(featureGenerator(Bonus::IN_FRENZY, 0, VLC->spellh->spells[56]->powers[sse.val]/100.0, sse.turnsRemain));
 // 		sf.back().id = sse.id;
 // 		break;
 // 	case 58: //counterstrike
@@ -1643,10 +1643,6 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 	BOOST_FOREACH(CGObjectInstance *obj, map->objects)
 	{
 		randomizeObject(obj);
-		if(obj->ID==EVENTI_TYPE)
-		{
-			obj->defInfo->handler=NULL;
-		}
 		obj->hoverName = VLC->generaltexth->names[obj->ID];
 
 		//handle Favouring Winds - mark tiles under it
@@ -2088,7 +2084,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 		CSpell *s;
 		for(unsigned int z=0; z<vti->obligatorySpells.size();z++)
 		{
-			s = &VLC->spellh->spells[vti->obligatorySpells[z]];
+			s = VLC->spellh->spells[vti->obligatorySpells[z]];
 			vti->spells[s->level-1].push_back(s->id);
 			vti->possibleSpells -= s->id;
 		}
@@ -2098,11 +2094,11 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 			int sel = -1;
 
 			for(unsigned int ps=0;ps<vti->possibleSpells.size();ps++)
-				total += VLC->spellh->spells[vti->possibleSpells[ps]].probabilities[vti->subID];
+				total += VLC->spellh->spells[vti->possibleSpells[ps]]->probabilities[vti->subID];
 			int r = (total)? ran()%total : -1;
 			for(unsigned int ps=0; ps<vti->possibleSpells.size();ps++)
 			{
-				r -= VLC->spellh->spells[vti->possibleSpells[ps]].probabilities[vti->subID];
+				r -= VLC->spellh->spells[vti->possibleSpells[ps]]->probabilities[vti->subID];
 				if(r<0)
 				{
 					sel = ps;
@@ -2112,7 +2108,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 			if(sel<0)
 				sel=0;
 
-			CSpell *s = &VLC->spellh->spells[vti->possibleSpells[sel]];
+			CSpell *s = VLC->spellh->spells[vti->possibleSpells[sel]];
 			vti->spells[s->level-1].push_back(s->id);
 			vti->possibleSpells -= s->id;
 		}
@@ -3225,7 +3221,7 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange( const CStack* attacker, con
 		{
 			if(defender->getCreature()->idNumber == affectedIds[g])
 			{
-				attackDefenceDifference += VLC->spellh->spells[55].powers[attacker->getEffect(55)->val];
+				attackDefenceDifference += VLC->spellh->spells[55]->powers[attacker->getEffect(55)->val];
 				break;
 			}
 		}
@@ -3302,7 +3298,7 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange( const CStack* attacker, con
 	}
 	if(attacker->getEffect(42)) //curse handling (partial, the rest is below)
 	{
-		multBonus *= 0.8f * float(VLC->spellh->spells[42].powers[attacker->getEffect(42)->val]); //the second factor is 1 or 0
+		multBonus *= 0.8f * float(VLC->spellh->spells[42]->powers[attacker->getEffect(42)->val]); //the second factor is 1 or 0
 	}
 
 	class HLP
@@ -3342,12 +3338,12 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange( const CStack* attacker, con
 
 	if(attacker->getEffect(42)) //curse handling (rest)
 	{
-		minDmg -= VLC->spellh->spells[42].powers[attacker->getEffect(42)->val];
+		minDmg -= VLC->spellh->spells[42]->powers[attacker->getEffect(42)->val];
 		returnedVal = std::make_pair(int(minDmg), int(minDmg));
 	}
 	else if(attacker->getEffect(41)) //bless handling
 	{
-		maxDmg += VLC->spellh->spells[41].powers[attacker->getEffect(41)->val];
+		maxDmg += VLC->spellh->spells[41]->powers[attacker->getEffect(41)->val];
 		returnedVal =  std::make_pair(int(maxDmg), int(maxDmg));
 	}
 	else
@@ -3453,8 +3449,8 @@ std::set<CStack*> BattleInfo::getAttackedCreatures( const CSpell * s, int skillL
 				attackedCres.insert(st);
 		}
 	}
-	else if(VLC->spellh->spells[s->id].attributes.find("CREATURE_TARGET_1") != std::string::npos
-		|| VLC->spellh->spells[s->id].attributes.find("CREATURE_TARGET_2") != std::string::npos) //spell to be cast on a specific creature but massive on expert
+	else if(VLC->spellh->spells[s->id]->attributes.find("CREATURE_TARGET_1") != std::string::npos
+		|| VLC->spellh->spells[s->id]->attributes.find("CREATURE_TARGET_2") != std::string::npos) //spell to be cast on a specific creature but massive on expert
 	{
 		if(skillLevel < 3)  /*not expert */
 		{
@@ -3467,8 +3463,8 @@ std::set<CStack*> BattleInfo::getAttackedCreatures( const CSpell * s, int skillL
 			for(int it=0; it<stacks.size(); ++it)
 			{
 				/*if it's non negative spell and our unit or non positive spell and hostile unit */
-				if((VLC->spellh->spells[s->id].positiveness >= 0 && stacks[it]->owner == attackerOwner)
-					||(VLC->spellh->spells[s->id].positiveness <= 0 && stacks[it]->owner != attackerOwner )
+				if((VLC->spellh->spells[s->id]->positiveness >= 0 && stacks[it]->owner == attackerOwner)
+					||(VLC->spellh->spells[s->id]->positiveness <= 0 && stacks[it]->owner != attackerOwner )
 					)
 				{
 					if(!onlyAlive || stacks[it]->alive())
@@ -3477,7 +3473,7 @@ std::set<CStack*> BattleInfo::getAttackedCreatures( const CSpell * s, int skillL
 			}
 		} //if(caster->getSpellSchoolLevel(s) < 3)
 	}
-	else if(VLC->spellh->spells[s->id].attributes.find("CREATURE_TARGET") != std::string::npos) //spell to be cast on one specific creature
+	else if(VLC->spellh->spells[s->id]->attributes.find("CREATURE_TARGET") != std::string::npos) //spell to be cast on one specific creature
 	{
 		CStack * st = getStackT(destinationTile, onlyAlive);
 		if(st)

+ 1 - 1
lib/HeroBonus.cpp

@@ -469,7 +469,7 @@ int NBonus::getCount(const CBonusSystemNode *obj, int from, int id)
 const CSpell * Bonus::sourceSpell() const
 {
 	if(source == SPELL_EFFECT)
-		return &VLC->spellh->spells[id];
+		return VLC->spellh->spells[id];
 	return NULL;
 }
 

+ 1 - 1
lib/IGameCallback.cpp

@@ -238,7 +238,7 @@ void IGameCallback::getAllowedSpells(std::vector<ui16> &out, ui16 level)
 	CSpell *spell;
 	for (int i = 0; i < gs->map->allowedSpell.size(); i++) //spellh size appears to be greater (?)
 	{
-		spell = &(VLC->spellh->spells[i]);
+		spell = VLC->spellh->spells[i];
 		if (isAllowed (0, spell->id) && spell->level == level)
 		{
 			out.push_back(spell->id);

+ 5 - 5
lib/NetPacksLib.cpp

@@ -1013,11 +1013,11 @@ DLL_EXPORT void BattleSpellCast::applyGs( CGameState *gs )
 		int spellCost = 0;
 		if(gs->curB)
 		{
-			spellCost = gs->curB->getSpellCost(&VLC->spellh->spells[id], h);
+			spellCost = gs->curB->getSpellCost(VLC->spellh->spells[id], h);
 		}
 		else
 		{
-			spellCost = VLC->spellh->spells[id].costs[skill];
+			spellCost = VLC->spellh->spells[id]->costs[skill];
 		}
 		h->mana -= spellCost;
 		if(h->mana < 0) h->mana = 0;
@@ -1040,7 +1040,7 @@ DLL_EXPORT void BattleSpellCast::applyGs( CGameState *gs )
 				//WTF?
 				for (BonusList::iterator it = remainingEff.begin(); it != remainingEff.end(); it++)
 				{
-					if (onlyHelpful && VLC->spellh->spells[ (*it)->id ].positiveness != 1)
+					if (onlyHelpful && VLC->spellh->spells[ (*it)->id ]->positiveness != 1)
 					{
 						remainingEff.push_back(*it);
 					}
@@ -1100,7 +1100,7 @@ DLL_EXPORT void BattleSpellCast::applyGs( CGameState *gs )
 			}
 		}
 
-		CStackInstance *csi = new CStackInstance(creID, h->getPrimSkillLevel(2) * VLC->spellh->spells[id].powers[skill]); //deleted by d-tor of summoned stack
+		CStackInstance *csi = new CStackInstance(creID, h->getPrimSkillLevel(2) * VLC->spellh->spells[id]->powers[skill]); //deleted by d-tor of summoned stack
 		csi->setArmyObj(h);
 		CStack * summonedStack = gs->curB->generateNewStack(*csi, gs->curB->stacks.size(), !side, 255, pos);
 		summonedStack->state.insert(SUMMONED);
@@ -1215,7 +1215,7 @@ DLL_EXPORT void StacksHealedOrResurrected::applyGs( CGameState *gs )
 			
 			for (BonusList::iterator it = changedStack->bonuses.begin(); it != changedStack->bonuses.end(); it++)
 			{
-				if(VLC->spellh->spells[(*it)->id].positiveness < 0)
+				if(VLC->spellh->spells[(*it)->id]->positiveness < 0)
 				{
 					changedStack->bonuses.erase(it);
 				}

+ 1 - 1
lib/map.cpp

@@ -1565,7 +1565,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 				{
 					int spellID = readNormalNr(bufor,i); 
 					i+=4;
-					innerArt = CArtifactInstance::createScroll(&VLC->spellh->spells[spellID]);
+					innerArt = CArtifactInstance::createScroll(VLC->spellh->spells[spellID]);
 				}
 				else if(art->ID == 5) //specific artifact
 				{

+ 6 - 6
server/CGameHandler.cpp

@@ -2394,7 +2394,7 @@ void CGameHandler::useScholarSkill(si32 fromHero, si32 toHero)
 	cs1.learn = true;
 	cs1.hid = toHero;//giving spells to first hero
 		for(std::set<ui32>::const_iterator it=h1->spells.begin(); it!=h1->spells.end();it++)
-			if ( h2Lvl >= VLC->spellh->spells[*it].level && !vstd::contains(h2->spells, *it))//hero can learn it and don't have it yet
+			if ( h2Lvl >= VLC->spellh->spells[*it]->level && !vstd::contains(h2->spells, *it))//hero can learn it and don't have it yet
 				cs1.spells.insert(*it);//spell to learn
 
 	ChangeSpells cs2;
@@ -2402,7 +2402,7 @@ void CGameHandler::useScholarSkill(si32 fromHero, si32 toHero)
 	cs2.hid = fromHero;
 
 	for(std::set<ui32>::const_iterator it=h2->spells.begin(); it!=h2->spells.end();it++)
-		if ( h1Lvl >= VLC->spellh->spells[*it].level && !vstd::contains(h1->spells, *it))
+		if ( h1Lvl >= VLC->spellh->spells[*it]->level && !vstd::contains(h1->spells, *it))
 			cs2.spells.insert(*it);
 			
 	if (cs1.spells.size() || cs2.spells.size())//create a message
@@ -3954,7 +3954,7 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
 		cs.learn = 1;
 		for(int i=0;i<VLC->spellh->spells.size();i++)
 		{
-			if(!VLC->spellh->spells[i].creatureAbility)
+			if(!VLC->spellh->spells[i]->creatureAbility)
 				cs.spells.insert(i);
 		}
 
@@ -4160,7 +4160,7 @@ static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHero
 void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destination, ui8 casterSide, ui8 casterColor,
 	const CGHeroInstance * caster, const CGHeroInstance * secHero, int usedSpellPower )
 {
-	CSpell *spell = &VLC->spellh->spells[spellID];
+	const CSpell *spell = VLC->spellh->spells[spellID];
 
 	BattleSpellCast sc;
 	sc.side = casterSide;
@@ -4343,7 +4343,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 				return false;
 			}
 
-			const CSpell *s = &VLC->spellh->spells[ba.additionalInfo];
+			const CSpell *s = VLC->spellh->spells[ba.additionalInfo];
 			ui8 skill = h->getSpellSchoolLevel(s); //skill level
 
 			if(   !(h->canCastThisSpell(s)) //hero cannot cast this spell at all
@@ -4937,7 +4937,7 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
 
 bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &pos)
 {
-	const CSpell *s = &VLC->spellh->spells[spellID];
+	const CSpell *s = VLC->spellh->spells[spellID];
 	int cost = h->getSpellCost(s);
 	int schoolLevel = h->getSpellSchoolLevel(s);