Pārlūkot izejas kodu

Sound patch from Ubuntux #6 - adds sound to units during combats
(vcmi_sound_battle.diff)

Michał W. Urbańczyk 16 gadi atpakaļ
vecāks
revīzija
6ccd9c2701

+ 20 - 1
CBattleInterface.cpp

@@ -57,7 +57,7 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
 	: attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1), 
 	  mouseHoveredStack(-1), previouslyHoveredHex(-1), spellDestSelectMode(false), spellToCast(NULL),
 	  attackingInfo(NULL), givenCommand(NULL), myTurn(false), resWindow(NULL), 
-	  showStackQueue(false), moveStarted(false)
+	  showStackQueue(false), moveStarted(false), moveSh(-1)
 {
 	pos = myRect;
 	strongInterest = true;
@@ -1099,6 +1099,7 @@ void CBattleInterface::stackMoved(int number, int destHex, bool endMoving, int d
 	}
 	if(moveStarted)
 	{
+		moveSh = CGI->mush->playSound(movedStack->creature->sounds.move, -1);
 		CGI->curh->hide();
 		creAnims[number]->setType(0);
 		moveStarted = false;
@@ -1205,6 +1206,7 @@ void CBattleInterface::stackMoved(int number, int destHex, bool endMoving, int d
 		}
 		creAnims[number]->setType(2); //resetting to default
 		CGI->curh->show();
+		CGI->mush->stopSound(moveSh);
 	}
 
 	CStack curs = *LOCPLINT->cb->battleGetStackByID(number);
@@ -1274,12 +1276,17 @@ void CBattleInterface::stacksAreAttacked(std::vector<CBattleInterface::SStackAtt
 	int maxLen = 0;
 	for(size_t g=0; g<attackedInfos.size(); ++g)
 	{
+		CStack attacked = *LOCPLINT->cb->battleGetStackByID(attackedInfos[g].ID);
+			
 		if(attackedInfos[g].killed)
 		{
+			CGI->mush->playSound(attacked.creature->sounds.killed);
 			creAnims[attackedInfos[g].ID]->setType(5); //death
 		}
 		else
 		{
+			// TODO: this block doesn't seems correct if the unit is defending.
+			CGI->mush->playSound(attacked.creature->sounds.wince);
 			creAnims[attackedInfos[g].ID]->setType(3); //getting hit
 		}
 	}
@@ -1460,6 +1467,7 @@ void CBattleInterface::stackAttacking(int ID, int dest)
 	attackingInfo->reversing = false;
 	attackingInfo->posShiftDueToDist = reversedShift;
 	attackingInfo->shooting = false;
+	attackingInfo->sh = -1;
 
 	switch(BattleInfo::mutualPosition(aStack.position + reversedShift, dest)) //attack direction
 	{
@@ -1756,6 +1764,7 @@ void CBattleInterface::stackIsShooting(int ID, int dest)
 	attackingInfo->reversing = false;
 	attackingInfo->posShiftDueToDist = 0;
 	attackingInfo->shooting = true;
+	attackingInfo->sh = -1;
 	if(projectileAngle > straightAngle) //upper shot
 		attackingInfo->shootingGroup = 14;
 	else if(projectileAngle < -straightAngle) //lower shot
@@ -2024,10 +2033,20 @@ void CBattleInterface::attackingShowHelper()
 			CStack aStack = *LOCPLINT->cb->battleGetStackByID(attackingInfo->ID); //attacking stack
 			if(attackingInfo->shooting)
 			{
+				// TODO: I see that we enter this function twice with
+				// attackingInfo->frame==0, so all the inits are done
+				// twice. The following is just a workaround until
+				// that is fixed. Once done, we can get rid of
+				// attackingInfo->sh
+				if (attackingInfo->sh == -1)
+					attackingInfo->sh = CGI->mush->playSound(aStack.creature->sounds.shoot);
 				creAnims[attackingInfo->ID]->setType(attackingInfo->shootingGroup);
 			}
 			else
 			{
+				// TODO: see comment above
+				if (attackingInfo->sh == -1)
+					attackingInfo->sh = CGI->mush->playSound(aStack.creature->sounds.attack);
 				if(aStack.creature->isDoubleWide())
 				{
 					switch(BattleInfo::mutualPosition(aStack.position+attackingInfo->posShiftDueToDist, attackingInfo->dest)) //attack direction

+ 2 - 0
CBattleInterface.h

@@ -191,6 +191,7 @@ private:
 		int posShiftDueToDist;
 		bool shooting;
 		int shootingGroup; //if shooting is true, print this animation group
+		int sh;			   // temporary sound handler
 	} * attackingInfo;
 	void attackingShowHelper();
 	void redrawBackgroundWithHexes(int activeStack);
@@ -240,6 +241,7 @@ public:
 	bool showStackQueue; //if true, queue of stacks will be shown
 
 	bool moveStarted; //if true, the creature that is already moving is going to make its first step
+	int moveSh;		  // sound handler used when moving a unit
 
 	//button handle funcs:
 	void bOptionsf();

+ 1 - 0
CMT.cpp

@@ -130,6 +130,7 @@ int main(int argc, char** argv)
 		tlog0<<"Loading .lod files: "<<tmh.getDif()<<std::endl;
 		initDLL(cgi->bitmaph,::console,logfile);
 		CGI->setFromLib();
+		cgi->mush->initCreaturesSounds(CGI->creh->creatures);
 		tlog0<<"Initializing VCMI_Lib: "<<tmh.getDif()<<std::endl;
 		pomtime.getDif();
 		cgi->curh = new CCursorHandler;

+ 211 - 0
config/cr_sounds.txt

@@ -0,0 +1,211 @@
+# Format is: <creature number> <attack> <defend> <killed> <move> <shoot> <wince> <ext1> <ext2>
+# All fields are mandatory, except ext1 and ext2.
+# If a sound doesn't exist or is not applicable, use invalid.
+
+AdvancedLizardman ALIZATTK.wav ALIZDFND.wav ALIZKILL.wav ALIZMOVE.wav ALIZSHOT.wav ALIZWNCE.wav
+AirElemental AELMATTK.wav AELMDFND.wav AELMKILL.wav AELMMOVE.wav invalid AELMWNCE.wav
+AmmoCart invalid invalid CARTKILL.wav invalid invalid CARTWNCE.wav
+AncientBehemoth BMTHATTK.wav BMTHDFND.wav BMTHKILL.wav BMTHMOVE.wav invalid BMTHWNCE.wav
+Angel ANGLATTK.wav ANGLDFND.wav ANGLKILL.wav ANGLMOVE.wav invalid ANGLWNCE.wav
+ApprenticeGremlin AGRMATTK.wav AGRMDFND.wav AGRMKILL.wav AGRMMOVE.wav AGRMSHOT.wav AGRMWNCE.wav
+ArchDevil ADVLATTK.wav ADVLDFND.wav ADVLKILL.wav ADVLMOVE.wav invalid ADVLWNCE.wav ADVLEXT1.wav ADVLEXT2.wav
+ArchMage AMAGATTK.wav AMAGDFND.wav AMAGKILL.wav AMAGMOVE.wav AMAGSHOT.wav AMAGWNCE.wav
+Archangel AAGLATTK.wav AAGLDFND.wav AAGLKILL.wav AAGLMOVE.wav invalid AAGLWNCE.wav
+AzureDragon AZURATTK.wav AZURDFND.wav AZURKILL.wav AZURMOVE.wav invalid AZURWNCE.wav
+Ballista invalid  invalid BALLKILL.wav invalid BALLSHOT.wav BALLWNCE.wav
+Basilisk BASLATTK.wav BASLDFND.wav BASLKILL.wav BASLMOVE.wav invalid BASLWNCE.wav
+BattleDwarf BDRFATTK.wav BDRFDFND.wav BDRFKILL.wav BDRFMOVE.wav invalid BDRFWNCE.wav
+Beholder BHDRATTK.wav BHDRDFND.wav BHDRKILL.wav BHDRMOVE.wav BHDRSHOT.wav BHDRWNCE.wav BHDRDETH.wav
+BlackDragon BKDRATTK.wav BKDRDFND.wav BKDRKILL.wav BKDRMOVE.wav invalid BKDRWNCE.wav
+BlackKnight BKNTATTK.wav BKNTDFND.wav BKNTKILL.wav BKNTMOVE.wav invalid BKNTWNCE.wav
+BlackLord BLRDATTK.wav BLRDDFND.wav BLRDKILL.wav BLRDMOVE.wav invalid BLRDWNCE.wav
+Boar BOARATTK.wav BOARDFND.wav BOARKILL.wav BOARMOVE.wav invalid BOARWNCE.wav
+BoneDragon BODRATTK.wav BODRDFND.wav BODRKILL.wav BODRMOVE.wav invalid BODRWNCE.wav
+BriarTreefolk BTREATTK.wav BTREDFND.wav BTREKILL.wav BTREMOVE.wav invalid BTREWNCE.wav
+BronzeGorgon BGORATTK.wav BGORDFND.wav BGORKILL.wav BGORMOVE.wav invalid BGORWNCE.wav
+Caliph CALFATTK.wav CALFDFND.wav CALFKILL.wav CALFMOVE.wav CALFSHOT.wav CALFWNCE.wav
+Catapult invalid invalid CATAKILL.wav invalid CATASHOT.wav CATAWNCE.wav
+Cavalier CAVAATTK.wav CAVADFND.wav CAVAKILL.wav CAVAMOVE.wav invalid CAVAWNCE.wav
+Centaur CNTRATTK.wav CNTRDFND.wav CNTRKILL.wav CNTRMOVE.wav CNTRSHOT.wav CNTRWNCE.wav
+Cerberus CERBATTK.wav CERBDFND.wav CERBKILL.wav CERBMOVE.wav invalid CERBWNCE.wav
+Champion CHMPATTK.wav CHMPDFND.wav CHMPKILL.wav CHMPMOVE.wav invalid CHMPWNCE.wav
+ChaosHydra CHYDATTK.wav CHYDDFND.wav CHYDKILL.wav CHYDMOVE.wav invalid CHYDWNCE.wav
+CopperGorgon CGORATTK.wav CGORDFND.wav CGORKILL.wav CGORMOVE.wav invalid CGORWNCE.wav
+Crusader CRUSATTK.wav CRUSDFND.wav CRUSKILL.wav CRUSMOVE.wav invalid CRUSWNCE.wav
+CrystalDragon CRYSATTK.wav CRYSDFND.wav CRYSKILL.wav CRYSMOVE.wav invalid CRYSWNCE.wav
+Cyclops CCYCATTK.wav CCYCDFND.wav CCYCKILL.wav CCYCMOVE.wav CCYCSHOT.wav CCYCWNCE.wav
+CyclopsLord CYCLATTK.wav CYCLDFND.wav CYCLKILL.wav CYCLMOVE.wav CYCLSHOT.wav CYCLWNCE.wav
+Devil DEVLATTK.wav DEVLDFND.wav DEVLKILL.wav DEVLMOVE.wav invalid DEVLWNCE.wav DEVLEXT1.wav DEVLEXT2.wav
+DiamondGolem DGLMATTK.wav DGLMDFND.wav DGLMKILL.wav DGLMMOVE.wav invalid DGLMWNCE.wav
+DragonFly DFLYATTK.wav DFLYDFND.wav DFLYKILL.wav DFLYMOVE.wav invalid DFLYWNCE.wav
+Dual-HornedDemon DHDMATTK.wav DHDMDFND.wav DHDMKILL.wav DHDMMOVE.wav invalid DHDMWNCE.wav
+Dwarf DWRFATTK.wav DWRFDFND.wav DWRFKILL.wav DWRFMOVE.wav invalid DWRFWNCE.wav
+EarthElemental EELMATTK.wav EELMDFND.wav EELMKILL.wav EELMMOVE.wav invalid EELMWNCE.wav
+Efreet EFRTATTK.wav EFRTDFND.wav EFRTKILL.wav EFRTMOVE.wav invalid EFRTWNCE.wav
+EfreetSultan ESULATTK.wav ESULDFND.wav ESULKILL.wav ESULMOVE.wav ESULSHOT.wav ESULWNCE.wav
+ElectricityElemental ENERATTK.wav ENERDFND.wav ENERKILL.wav ENERMOVE.wav invalid ENERWNCE.wav
+EliteCentaur ECNTATTK.wav ECNTDFND.wav ECNTKILL.wav ECNTMOVE.wav invalid ECNTWNCE.wav
+Enchanter ENCHATTK.wav ENCHDFND.wav ENCHKILL.wav ENCHMOVE.wav ENCHSHOT.wav ENCHWNCE.wav
+EvilEye EVLIATTK.wav EVLIDFND.wav EVLIKILL.wav EVLIMOVE.wav EVLISHOT.wav EVLIWNCE.wav EVLIDETH.wav
+FairieDragon FAERATTK.wav FAERDFND.wav FAERKILL.wav FAERMOVE.wav FAERSHOT.wav FAERWNCE.wav
+Familiar FMLRATTK.wav FMLRDFND.wav FMLRKILL.wav FMLRMOVE.wav invalid FMLRWNCE.wav
+FireDragonFly FDFLATTK.wav FDFLDFND.wav FDFLKILL.wav FDFLMOVE.wav FDFLSHOT.wav FDFLWNCE.wav
+FireElemental FELMATTK.wav FELMDFND.wav FELMKILL.wav FELMMOVE.wav invalid FELMWNCE.wav
+Firebird FIRBATTK.wav FIRBDFND.wav FIRBKILL.wav FIRBMOVE.wav invalid FIRBWNCE.wav
+FirstAidTent invalid invalid FAIDKILL.wav invalid invalid FAIDWNCE.wav
+Genie GENIATTK.wav GENIDFND.wav GENIKILL.wav GENIMOVE.wav invalid GENIWNCE.wav
+GhostDragon GHDRATTK.wav GHDRDFND.wav GHDRKILL.wav GHDRMOVE.wav invalid GHDRWNCE.wav
+Gnoll GNOLATTK.wav GNOLDFND.wav GNOLKILL.wav GNOLMOVE.wav invalid GNOLWNCE.wav
+GnollMarauder GNLMATTK.wav GNLMDFND.wav GNLMKILL.wav GNLMMOVE.wav invalid GNLMWNCE.wav
+Goblin GBLNATTK.wav GBLNDFND.wav GBLNKILL.wav GBLNMOVE.wav invalid GBLNWNCE.wav
+GoblinWolfRider GWRDATTK.wav GWRDDFND.wav GWRDKILL.wav GWRDMOVE.wav invalid GWRDWNCE.wav
+Gog GOGGATTK.wav GOGGDFND.wav GOGGKILL.wav GOGGMOVE.wav GOGGSHOT.wav GOGGWNCE.wav GOGFLAME.wav
+GoldDragon GODRATTK.wav GODRDFND.wav GODRKILL.wav GODRMOVE.wav invalid GODRWNCE.wav
+GoldGolem GGLMATTK.wav GGLMDFND.wav GGLMKILL.wav GGLMMOVE.wav invalid GGLMWNCE.wav
+GrandElf GELFATTK.wav GELFDFND.wav GELFKILL.wav GELFMOVE.wav GELFSHOT.wav GELFWNCE.wav
+GreaterBasilisk GBASATTK.wav GBASDFND.wav GBASKILL.wav GBASMOVE.wav invalid GBASWNCE.wav
+GreaterTitan GTITATTK.wav GTITDFND.wav GTITKILL.wav GTITMOVE.wav GTITSHOT.wav GTITWNCE.wav
+GreenDragon GRDRATTK.wav GRDRDFND.wav GRDRKILL.wav GRDRMOVE.wav invalid GRDRWNCE.wav
+Griffin GRIFATTK.wav GRIFDFND.wav GRIFKILL.wav GRIFMOVE.wav invalid GRIFWNCE.wav
+Halberdier HALBATTK.wav HALBDFND.wav HALBKILL.wav HALBMOVE.wav invalid HALBWNCE.wav
+Halfling HALFATTK.wav HALFDFND.wav HALFKILL.wav HALFMOVE.wav HALFSHOT.wav HALFWNCE.wav
+Harpy HARPATTK.wav HARPDFND.wav HARPKILL.wav HARPMOVE.wav silence HARPWNCE.wav
+HarpyHag HHAGATTK.wav HHAGDFND.wav HHAGKILL.wav HHAGMOVE.wav HHAGSHOT.wav HHAGWNCE.wav
+HeavyCrossbowman HCRSATTK.wav HCRSDFND.wav HCRSKILL.wav HCRSMOVE.wav HCRSSHOT.wav HCRSWNCE.wav
+HellHound HHNDATTK.wav HHNDDFND.wav HHNDKILL.wav HHNDMOVE.wav invalid HHNDWNCE.wav
+Hobgoblin HGOBATTK.wav HGOBDFND.wav HGOBKILL.wav HGOBMOVE.wav invalid HGOBWNCE.wav
+HobgoblinWolfRider HGWRATTK.wav HGWRDFND.wav HGWRKILL.wav HGWRMOVE.wav invalid HGWRWNCE.wav
+Hydra HYDRATTK.wav HYDRDFND.wav HYDRKILL.wav HYDRMOVE.wav invalid HYDRWNCE.wav
+IceElemental ICELATTK.wav ICELDFND.wav ICELKILL.wav ICELMOVE.wav ICELSHOT.wav ICELWNCE.wav
+Imp IMPPATTK.wav IMPPDFND.wav IMPPKILL.wav IMPPMOVE.wav invalid IMPPWNCE.wav
+InfernalTroglodyte ITRGATTK.wav ITRGDFND.wav ITRGKILL.wav ITRGMOVE.wav invalid ITRGWNCE.wav
+IronGolem IGLMATTK.wav IGLMDFND.wav IGLMKILL.wav IGLMMOVE.wav invalid IGLMWNCE.wav
+LesserTitan LTITATTK.wav LTITDFND.wav LTITKILL.wav LTITMOVE.wav invalid LTITWNCE.wav
+Lich LICHATTK.wav LICHDFND.wav LICHKILL.wav LICHMOVE.wav LICHSHOT.wav LICHWNCE.wav LICHATK2.wav
+LightCrossbowman LCRSATTK.wav LCRSDFND.wav LCRSKILL.wav LCRSMOVE.wav LCRSSHOT.wav LCRSWNCE.wav
+Mage MAGEATTK.wav MAGEDFND.wav MAGEKILL.wav MAGEMOVE.wav MAGESHOT.wav MAGEWNCE.wav
+MagicElemental MGELATTK.wav MGELDFND.wav MGELKILL.wav MGELMOVE.wav invalid MGELWNCE.wav
+Magog MGOGATTK.wav MGOGDFND.wav MGOGKILL.wav MGOGMOVE.wav MGOGSHOT.wav MGOGWNCE.wav GOGFLAME.wav
+Manticore MANTATTK.wav MANTDFND.wav MANTKILL.wav MANTMOVE.wav MANTSHOT.wav MANTWNCE.wav
+MasterGremlin MGRMATTK.wav MGRMDFND.wav MGRMKILL.wav MGRMMOVE.wav MGRMSHOT.wav MGRMWNCE.wav
+Medusa MEDUATTK.wav MEDUDFND.wav MEDUKILL.wav MEDUMOVE.wav MEDUSHOT.wav MEDUWNCE.wav
+MedusaQueen MEDQATTK.wav MEDQDFND.wav MEDQKILL.wav MEDQMOVE.wav MEDQSHOT.wav MEDQWNCE.wav
+Minotaur MINOATTK.wav MINODFND.wav MINOKILL.wav MINOMOVE.wav invalid MINOWNCE.wav
+MinotaurKing MINKATTK.wav MINKDFND.wav MINKKILL.wav MINKMOVE.wav MINKSHOT.wav MINKWNCE.wav
+Monk MONKATTK.wav MONKDFND.wav MONKKILL.wav MONKMOVE.wav MONKSHOT.wav MONKWNCE.wav
+Mummy MUMYATTK.wav MUMYDFND.wav MUMYKILL.wav MUMYMOVE.wav invalid MUMYWNCE.wav
+NagaGuardian NGRDATTK.wav NGRDDFND.wav NGRDKILL.wav NGRDMOVE.wav invalid NGRDWNCE.wav
+NagaSentinel NSENATTK.wav NSENDFND.wav NSENKILL.wav NSENMOVE.wav invalid NSENWNCE.wav
+Nosferatu NOSFATTK.wav NOSFDFND.wav NOSFEXT1.wav NOSFEXT2.wav NOSFKILL.wav NOSFMOVE.wav NOSFSHOT.wav NOSFWNCE.wav
+ObsidianGargoyle OGRGATTK.wav OGRGDFND.wav OGRGKILL.wav OGRGMOVE.wav invalid OGRGWNCE.wav
+Ogre OGREATTK.wav OGREDFND.wav OGREKILL.wav OGREMOVE.wav invalid OGREWNCE.wav
+OgreMage OGRMATTK.wav OGRMDFND.wav OGRMKILL.wav OGRMMOVE.wav OGRMSHOT.wav OGRMWNCE.wav
+Orc OORCATTK.wav OORCDFND.wav OORCKILL.wav OORCMOVE.wav OORCSHOT.wav OORCWNCE.wav
+OrcChieftain ORCCATTK.wav ORCCDFND.wav ORCCKILL.wav ORCCMOVE.wav ORCCSHOT.wav ORCCWNCE.wav
+Peasant PSNTATTK.wav PSNTDFND.wav PSNTKILL.wav PSNTMOVE.wav invalid PSNTWNCE.wav
+Pegasus PEGAATTK.wav PEGADFND.wav PEGAKILL.wav PEGAMOVE.wav invalid PEGAWNCE.wav
+Pheonix PHOEATTK.wav PHOEDFND.wav PHOEKILL.wav PHOEMOVE.wav invalid PHOEWNCE.wav
+Pikeman PIKEATTK.wav PIKEDFND.wav PIKEKILL.wav PIKEMOVE.wav invalid PIKEWNCE.wav
+PitFiend PFNDATTK.wav PFNDDFND.wav PFNDKILL.wav PFNDMOVE.wav invalid PFNDWNCE.wav
+PitFoe PFOEATTK.wav PFOEDFND.wav PFOEKILL.wav PFOEMOVE.wav invalid PFOEWNCE.wav
+Pixie PIXIATTK.wav PIXIDFND.wav PIXIKILL.wav PIXIMOVE.wav invalid PIXIWNCE.wav
+PowerLich PLCHATTK.wav PLCHDFND.wav PLCHKILL.wav PLCHMOVE.wav PLCHSHOT.wav PLCHWNCE.wav
+PrimitiveLizardman PLIZATTK.wav PLIZDFND.wav PLIZKILL.wav PLIZMOVE.wav PLIZSHOT.wav PLIZWNCE.wav
+PsiElemental PSYCATTK.wav PSYCDFND.wav PSYCKILL.wav PSYCMOVE.wav invalid PSYCWNCE.wav
+RedDragon RDDRATTK.wav RDDRDFND.wav RDDRKILL.wav RDDRMOVE.wav invalid RDDRWNCE.wav
+Roc ROCCATTK.wav ROCCDFND.wav ROCCKILL.wav ROCCMOVE.wav invalid ROCCWNCE.wav
+Rogue ROGUATTK.wav ROGUDFND.wav ROGUKILL.wav ROGUMOVE.wav invalid ROGUWNCE.wav
+RoyalGriffin RGRFATTK.wav RGRFDFND.wav RGRFKILL.wav RGRFMOVE.wav invalid RGRFWNCE.wav
+RustDragon RUSTATTK.wav RUSTDFND.wav RUSTKILL.wav RUSTMOVE.wav invalid RUSTWNCE.wav
+Scorpicore SCRPATTK.wav SCRPDFND.wav SCRPKILL.wav SCRPMOVE.wav SCRPSHOT.wav SCRPWNCE.wav
+SilverPegasus APEGATTK.wav APEGDFND.wav APEGKILL.wav APEGMOVE.wav invalid APEGWNCE.wav
+Single-HornedDemon SHDMATTK.wav SHDMDFND.wav SHDMKILL.wav SHDMMOVE.wav invalid SHDMWNCE.wav
+Skeleton SKELATTK.wav SKELDFND.wav SKELKILL.wav SKELMOVE.wav invalid SKELWNCE.wav
+SkeletonWarrior SKLWATTK.wav SKLWDFND.wav SKLWKILL.wav SKLWMOVE.wav invalid SKLWWNCE.wav
+Sprite SPRTATTK.wav SPRTDFND.wav SPRTKILL.wav SPRTMOVE.wav invalid SPRTWNCE.wav
+StoneGargoyle SGRGATTK.wav SGRGDFND.wav SGRGKILL.wav SGRGMOVE.wav invalid SGRGWNCE.wav
+StoneGolem SGLMATTK.wav SGLMDFND.wav SGLMKILL.wav SGLMMOVE.wav invalid SGLMWNCE.wav
+StormElemental STORATTK.wav STORDFND.wav STORKILL.wav STORMOVE.wav STORSHOT.wav STORWNCE.wav
+Swordsman SWRDATTK.wav SWRDDFND.wav SWRDKILL.wav SWRDMOVE.wav invalid SWRDWNCE.wav
+Thunderbird TBRDATTK.wav TBRDDFND.wav TBRDKILL.wav TBRDMOVE.wav invalid TBRDWNCE.wav
+Treefolk TREEATTK.wav TREEDFND.wav TREEKILL.wav TREEMOVE.wav invalid TREEWNCE.wav
+Troglodyte TROGATTK.wav TROGDFND.wav TROGKILL.wav TROGMOVE.wav invalid TROGWNCE.wav
+Unicorn UNICATTK.wav UNICDFND.wav UNICKILL.wav UNICMOVE.wav invalid UNICWNCE.wav
+Vampire VAMPATTK.wav VAMPDFND.wav VAMPKILL.wav VAMPMOVE.wav invalid VAMPWNCE.wav VAMPEXT1.wav VAMPEXT2.wav
+WarUnicorn WUNCATTK.wav WUNCDFND.wav WUNCKILL.wav WUNCMOVE.wav WUNCSHOT.wav WUNCWNCE.wav
+WaterElemental WELMATTK.wav WELMDFND.wav WELMKILL.wav WELMMOVE.wav invalid WELMWNCE.wav
+Wight WGHTATTK.wav WGHTDFND.wav WGHTKILL.wav WGHTMOVE.wav invalid WGHTWNCE.wav
+WoodElf WELFATTK.wav WELFDFND.wav WELFKILL.wav WELFMOVE.wav WELFSHOT.wav WELFWNCE.wav
+Wraith WRTHATTK.wav WRTHDFND.wav WRTHKILL.wav WRTHMOVE.wav invalid WRTHWNCE.wav
+Wyvern WYVNATTK.wav WYVNDFND.wav WYVNKILL.wav WYVNMOVE.wav invalid WYVNWNCE.wav
+WyvernMonarch WYVMATTK.wav WYVMDFND.wav WYVMKILL.wav WYVMMOVE.wav invalid WYVMWNCE.wav
+YoungBehemoth YBMHATTK.wav YBMHDFND.wav YBMHKILL.wav YBMHMOVE.wav invalid YBMHWNCE.wav
+Zealot ZELTATTK.wav ZELTDFND.wav ZELTKILL.wav ZELTMOVE.wav ZELTSHOT.wav ZELTWNCE.wav
+Zombie ZOMBATTK.wav ZOMBDFND.wav ZOMBKILL.wav ZOMBMOVE.wav invalid ZOMBWNCE.wav
+ZombieLord ZMBLATTK.wav ZMBLDFND.wav ZMBLKILL.wav ZMBLMOVE.wav invalid ZMBLWNCE.wav
+
+# todo - troll ?
+# TRLLATTK.wav TRLLDFND.wav TRLLKILL.wav TRLLMOVE.wav invalid TRLLWNCE.wav
+
+# todo - nomad ?
+# NMADATTK.wav NMADDFND.wav NMADKILL.wav NMADMOVE.wav invalid NMADWNCE.wav
+
+# todo - magma ?
+# MAGMATTK.wav MAGMDFND.wav MAGMKILL.wav MAGMMOVE.wav invalid MAGMWNCE.wav
+
+
+# Missing entries
+# 125 StoneElemental
+# 128 FireElemental
+# 129 FireElemental
+# 137 Sharpshooter
+# 142 warrior
+# 144 OgreShaman
+# 149 ArrowTower
+# 150 SupremeArchangel
+# 151 DiamondDragon
+# 152 LordofThunder
+# 153 HellBaron
+# 154 BloodDragon
+# 155 DarknessDragon
+# 156 GhostBehemoth
+# 157 HellHydra
+# 158 SacredPhoenix
+# 159 Ghost
+# 160 God1War
+# 161 God2Peace
+# 162 God3Mana
+# 163 God4Lore
+# 164 MinotaurKing
+# 165 MineralElemental
+# 166 ElectricityElemental
+# 167 AncientBasilisk
+# 168 Gorynych
+# 169 WarZealot
+# 170 Myriad
+# 171 MedusaMatriarch
+# 172 Nightmare
+# 173 SantaGremlin
+# 174 Paladin1
+# 175 Hierophant1
+# 176 TempleGuardian1
+# 177 Succubus1
+# 178 SoulEater1
+# 179 Brute1
+# 180 OgreLeader1
+# 181 Shaman1
+# 182 AstralSpirit1
+# 183 Paladin2
+# 184 Hierophant2
+# 185 TempleGuardian2
+# 186 Succubus2
+# 187 SoulEater2
+# 188 Brute2
+# 189 OgreLeader2
+# 190 Shaman2
+# 191 AstralSpirit2
+# 192 SylvanCentaur
+# 193 Sorceress
+# 194 Werewolf
+# 195 HellSteed
+# 196 Dracolich

+ 9 - 0
hch/CCreatureHandler.cpp

@@ -99,6 +99,15 @@ void CCreatureHandler::loadCreatures()
 		CCreature ncre;
 		ncre.cost.resize(RESOURCE_QUANTITY);
 		ncre.level=0;
+		ncre.sounds.attack = soundBase::invalid;
+		ncre.sounds.defend = soundBase::invalid;
+		ncre.sounds.killed = soundBase::invalid;
+		ncre.sounds.move = soundBase::invalid;
+		ncre.sounds.shoot = soundBase::invalid;
+		ncre.sounds.wince = soundBase::invalid;
+		ncre.sounds.ext1 = soundBase::invalid;
+		ncre.sounds.ext2 = soundBase::invalid;
+
 		int befi=i;
 		for(i; i<andame; ++i)
 		{

+ 14 - 0
hch/CCreatureHandler.h

@@ -6,6 +6,8 @@
 #include <map>
 #include <set>
 
+#include "CSoundBase.h"
+
 /*
  * CCreatureHandler.h, part of VCMI engine
  *
@@ -42,6 +44,18 @@ public:
 	int troopCountLocationOffset, attackClimaxFrame;
 	///end of anim info
 
+	// Sound infos
+	struct {
+		soundBase::soundNames attack;
+		soundBase::soundNames defend;
+		soundBase::soundNames killed; // was killed died
+		soundBase::soundNames move;
+		soundBase::soundNames shoot; // range attack
+		soundBase::soundNames wince; // attacked but did not die
+		soundBase::soundNames ext1;	 // creature specific extension
+		soundBase::soundNames ext2;	 // creature specific extension
+	} sounds;
+
 	bool isDoubleWide() const; //returns true if unit is double wide on battlefield
 	bool isFlying() const; //returns true if it is a flying unit
 	bool isShooting() const; //returns true if unit can shoot

+ 73 - 1
hch/CMusicHandler.cpp

@@ -1,5 +1,6 @@
 #include "../stdafx.h"
 
+#include <sstream>
 #include <boost/assign/std/vector.hpp> 
 #include <boost/assign/list_of.hpp>
 
@@ -7,6 +8,8 @@
 
 #include "CSndHandler.h"
 #include "CMusicHandler.h"
+#include "CCreatureHandler.h"
+#include "../CGameInfo.h"
 
 /*
  * CMusicHandler.cpp, part of VCMI engine
@@ -46,6 +49,11 @@ void CMusicHandler::initMusics()
 		soundBase::horseSubterranean, soundBase::horseLava,
 		soundBase::horseWater, soundBase::horseRock;
 
+	// Create reverse map. It's used during game init to map names to internal IDs
+	std::map<soundBase::soundNames, cachedSounds>::iterator it;
+	for ( it=sounds.begin() ; it != sounds.end(); it++ )
+		reverse_sounds[(*it).second.filename] = (*it).first;
+
 	//AITheme0 = Mix_LoadMUS(DATA_DIR "MP3" PATHSEPARATOR "AITheme0.mp3");
 	//AITheme1 = Mix_LoadMUS(DATA_DIR "MP3" PATHSEPARATOR "AITHEME1.mp3");
 	//AITheme2 = Mix_LoadMUS(DATA_DIR "MP3" PATHSEPARATOR "AITHEME2.mp3");
@@ -113,7 +121,71 @@ Mix_Chunk *CMusicHandler::GetSoundChunk(std::string srcName)
 
 	return chunk;
 }
-  
+
+soundBase::soundNames CMusicHandler::getSoundID(std::string &fileName)
+{
+	std::map<std::string, soundBase::soundNames>::iterator it;
+
+	it = reverse_sounds.find(fileName);
+	if (it == reverse_sounds.end())
+		return soundBase::invalid;
+	else
+		return it->second;
+}
+
+void CMusicHandler::initCreaturesSounds(std::vector<CCreature> &creatures)
+{
+	tlog5 << "\t\tReading config/cr_sounds.txt" << std::endl;
+	std::ifstream ifs("config/cr_sounds.txt");
+	std::string line;
+
+	while(getline(ifs, line))
+	{
+		std::string cname="", attack="", defend="", killed="", move="", 
+			shoot="", wince="", ext1="", ext2="";
+		std::stringstream str(line);
+
+		str >> cname >> attack >> defend >> killed >> move >> shoot >> wince >> ext1 >> ext2;
+
+		if (cname[0] == '#')
+			// That's a comment. Discard.
+			continue;
+
+		if (str.good() || (str.eof() && wince != ""))
+		{
+			int id = CGI->creh->nameToID[cname];
+			CCreature &c = CGI->creh->creatures[id];
+
+			if (c.sounds.killed != soundBase::invalid)
+				tlog1 << "Creature << " << cname << " already has sounds" << std::endl;
+			
+			c.sounds.attack = getSoundID(attack);
+			c.sounds.defend = getSoundID(defend);
+			c.sounds.killed = getSoundID(killed);
+			c.sounds.move = getSoundID(move);
+			c.sounds.shoot = getSoundID(shoot);
+			c.sounds.wince = getSoundID(wince);
+			c.sounds.ext1 = getSoundID(ext1);
+			c.sounds.ext2 = getSoundID(ext2);
+		}
+	}
+	ifs.close();
+	ifs.clear();
+
+	// Find creatures without sounds
+	for(unsigned int i=0;i<CGI->creh->creatures.size();i++)
+	{
+		// Note: this will exclude war machines, but it's better
+		// than nothing.
+		if (vstd::contains(CGI->creh->notUsedMonsters, i))
+			continue;
+
+		CCreature &c = CGI->creh->creatures[i];
+		if (c.sounds.killed == soundBase::invalid)
+			tlog1 << "creature " << c.idNumber << " doesn't have sounds" << std::endl;
+	}
+}
+
 // Plays a sound, and return its channel so we can fade it out later
 int CMusicHandler::playSound(soundBase::soundNames soundID, int repeats)
 {

+ 4 - 0
hch/CMusicHandler.h

@@ -20,6 +20,7 @@ class CMusicHandler
 {
 private:
 	CSndHandler *sndh;
+	soundBase::soundNames getSoundID(std::string &fileName);
 
 	class cachedSounds {
 	public:
@@ -33,12 +34,15 @@ private:
 	};
 
 	std::map<soundBase::soundNames, cachedSounds> sounds;
+	std::map<std::string, soundBase::soundNames> reverse_sounds;
 
 	Mix_Chunk *GetSoundChunk(std::string srcName);
 
 public:
 	CMusicHandler(): sndh(NULL) {};
+
 	void initMusics();
+	void initCreaturesSounds(std::vector<CCreature> &creatures);
 
 	// Sounds
 	int playSound(soundBase::soundNames soundID, int repeats=0);