瀏覽代碼

* added slow spell
* a few mistakes in AC_desc.txt fixed
* appropriate spells cannot be casted at any tile
* small memory optimizations in CDefHandler
* minor fixes

mateuszb 17 年之前
父節點
當前提交
d2db5ba18e
共有 9 個文件被更改,包括 152 次插入28 次删除
  1. 100 10
      CBattleInterface.cpp
  2. 1 0
      CBattleInterface.h
  3. 1 1
      CGameState.cpp
  4. 3 3
      config/AC_desc.txt
  5. 7 9
      hch/CDefHandler.cpp
  6. 1 5
      hch/CDefHandler.h
  7. 28 0
      hch/CObjectHandler.cpp
  8. 1 0
      hch/CObjectHandler.h
  9. 10 0
      server/CGameHandler.cpp

+ 100 - 10
CBattleInterface.cpp

@@ -7,6 +7,7 @@
 #include "hch/CObjectHandler.h"
 #include "hch/CHeroHandler.h"
 #include "hch/CDefHandler.h"
+#include "hch/CSpellHandler.h"
 #include "CCursorHandler.h"
 #include "CCallback.h"
 #include "CGameState.h"
@@ -410,7 +411,7 @@ void CBattleInterface::show(SDL_Surface * to)
 	std::vector< std::list<SBattleEffect>::iterator > toErase;
 	for(std::list<SBattleEffect>::iterator it = battleEffects.begin(); it!=battleEffects.end(); ++it)
 	{
-		blitAt(it->anim->ourImages[it->frame].bitmap, it->x, it->y, to);
+		blitAt(it->anim->ourImages[(it->frame)%it->anim->ourImages.size()].bitmap, it->x, it->y, to);
 		++(it->frame);
 
 		if(it->frame == it->maxFrame)
@@ -565,6 +566,51 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 			}
 		}
 	}
+	else if(spellDestSelectMode)
+	{
+		int myNumber = -1; //number of hovered tile
+		for(int g=0; g<BFIELD_SIZE; ++g)
+		{
+			if(bfield[g].hovered && bfield[g].strictHovered)
+			{
+				myNumber = g;
+				break;
+			}
+		}
+		if(myNumber == -1)
+		{
+			CGI->curh->changeGraphic(1, 0);
+		}
+		else
+		{
+			switch(spellSelMode)
+			{
+			case 0:
+				CGI->curh->changeGraphic(3, 0);
+				break;
+			case 1:
+				if(LOCPLINT->cb->battleGetStackByPos(myNumber) && LOCPLINT->playerID == LOCPLINT->cb->battleGetStackByPos(myNumber)->owner )
+					CGI->curh->changeGraphic(3, 0);
+				else
+					CGI->curh->changeGraphic(1, 0);
+				break;
+			case 2:
+				if(LOCPLINT->cb->battleGetStackByPos(myNumber) && LOCPLINT->playerID != LOCPLINT->cb->battleGetStackByPos(myNumber)->owner )
+					CGI->curh->changeGraphic(3, 0);
+				else
+					CGI->curh->changeGraphic(1, 0);
+				break;
+			case 3:
+				if(LOCPLINT->cb->battleGetStackByPos(myNumber))
+					CGI->curh->changeGraphic(3, 0);
+				else
+					CGI->curh->changeGraphic(1, 0);
+				break;
+			case 4: //TODO: implement this case
+				break;
+			}
+		}
+	}
 }
 
 bool CBattleInterface::reverseCreature(int number, int hex, bool wideTrick)
@@ -1077,12 +1123,35 @@ void CBattleInterface::hexLclicked(int whichOne)
 			return; //we are not permit to do anything
 		if(spellDestSelectMode)
 		{
-			spellToCast->destinationTile = whichOne;
-			LOCPLINT->cb->battleMakeAction(spellToCast);
-			delete spellToCast;
-			spellToCast = NULL;
-			spellDestSelectMode = false;
-			CGI->curh->changeGraphic(1, 6);
+			//checking destination
+			bool allowCasting = true;
+			switch(spellSelMode)
+			{
+			case 1:
+				if(!LOCPLINT->cb->battleGetStackByPos(whichOne) || LOCPLINT->playerID != LOCPLINT->cb->battleGetStackByPos(whichOne)->owner )
+					allowCasting = false;
+				break;
+			case 2:
+				if(!LOCPLINT->cb->battleGetStackByPos(whichOne) || LOCPLINT->playerID == LOCPLINT->cb->battleGetStackByPos(whichOne)->owner )
+					allowCasting = false;
+				break;
+			case 3:
+				if(!LOCPLINT->cb->battleGetStackByPos(whichOne))
+					allowCasting = false;
+				break;
+			case 4: //TODO: implement this case
+				break;
+			}
+			//destination checked
+			if(allowCasting)
+			{
+				spellToCast->destinationTile = whichOne;
+				LOCPLINT->cb->battleMakeAction(spellToCast);
+				delete spellToCast;
+				spellToCast = NULL;
+				spellDestSelectMode = false;
+				CGI->curh->changeGraphic(1, 6);
+			}
 		}
 		else
 		{
@@ -1282,11 +1351,16 @@ void CBattleInterface::spellCasted(SpellCasted * sc)
 			displayEffect(1, sc->tile);
 			break;
 		}
-	case 53://haste
+	case 53: //haste
 		{
 			displayEffect(31, sc->tile);
 			break;
 		}
+	case 54: //slow
+		{
+			displayEffect(19, sc->tile);
+			break;
+		}
 	}
 }
 
@@ -1300,6 +1374,22 @@ void CBattleInterface::castThisSpell(int spellID)
 	ba->side = defendingHeroInstance ? (LOCPLINT->playerID == defendingHeroInstance->tempOwner) : false;
 	spellToCast = ba;
 	spellDestSelectMode = true;
+
+	//choosing possible tragets
+	const CGHeroInstance * castingHero = (attackingHeroInstance->tempOwner == LOCPLINT->playerID) ? attackingHeroInstance : attackingHeroInstance;
+	spellSelMode = 0;
+	if(CGI->spellh->spells[spellID].attributes.find("CREATURE_TARGET") != std::string::npos)
+	{
+		spellSelMode = 3;
+	}
+	if(CGI->spellh->spells[spellID].attributes.find("CREATURE_TARGET_2") != std::string::npos)
+	{
+		if(castingHero && castingHero->getSpellSecLevel(spellID) < 3)
+			spellSelMode = 3;
+		else //TODO: no destination chould apply in this case
+		{
+		}
+	}
 	CGI->curh->changeGraphic(3, 0); 
 }
 
@@ -1311,8 +1401,8 @@ void CBattleInterface::displayEffect(ui32 effect, int destTile)
 		be.anim = CDefHandler::giveDef(graphics->battleACToDef[effect][0]);
 		be.frame = 0;
 		be.maxFrame = be.anim->ourImages.size();
-		be.x = 22 * ( ((destTile/BFIELD_WIDTH) + 1)%2 ) + 44 * (destTile % BFIELD_WIDTH) + 50;
-		be.y = 100 + 42 * (destTile/BFIELD_WIDTH);
+		be.x = 22 * ( ((destTile/BFIELD_WIDTH) + 1)%2 ) + 44 * (destTile % BFIELD_WIDTH) + 45;
+		be.y = 105 + 42 * (destTile/BFIELD_WIDTH);
 
 		if(effect != 1)
 		{

+ 1 - 0
CBattleInterface.h

@@ -135,6 +135,7 @@ private:
 	float getAnimSpeedMultiplier() const; //returns multiplier for number of frames in a group
 
 	bool spellDestSelectMode; //if true, player is choosing destination for his spell
+	int spellSelMode; //0 - any location, 1 - any firendly creature, 2 - any hostile creature, 3 - any creature, 4 - obstacle
 	BattleAction * spellToCast; //spell for which player is choosing destination
 
 	class CAttHelper

+ 1 - 1
CGameState.cpp

@@ -212,7 +212,7 @@ signed char BattleInfo::mutualPosition(int hex1, int hex2)
 }
 std::vector<int> BattleInfo::neighbouringTiles(int hex)
 {
-#define CHECK_AND_PUSH(tile) {int hlp = (tile); if(hlp>=0 && hlp<BFIELD_SIZE && (hlp%17!=16) && hlp%17) ret.push_back(hlp);}
+#define CHECK_AND_PUSH(tile) {int hlp = (tile); if(hlp>=0 && hlp<BFIELD_SIZE && (hlp%BFIELD_WIDTH!=16) && hlp%BFIELD_WIDTH) ret.push_back(hlp);}
 	std::vector<int> ret;
 	CHECK_AND_PUSH(hex - ( (hex/17)%2 ? 18 : 17 ));
 	CHECK_AND_PUSH(hex - ( (hex/17)%2 ? 17 : 16 ));

+ 3 - 3
config/AC_desc.txt

@@ -18,7 +18,7 @@
 16 1 C08SPE0.DEF
 17 1 C08SPF0.DEF
 18 1 C09SPA0.DEF
-19 3 C17SPE0.DEF C17SPE1.DEF C17SPE2.DEF
+19 1 C09SPE0.DEF
 20 1 C09SPW0.DEF
 21 1 C10SPA0.DEF
 22 1 C11SPE0.DEF
@@ -54,10 +54,10 @@
 52 1 C12SPE0.DEF
 53 2 C13SPF.DEF C13SPF0.DEF
 54 2 C16SPE.DEF C16SPE0.DEF
-55 1 C09SPE0.DEF
+55 1 C17SPE0.DEF
 56 1 C0ACID.DEF
 57 2 C09SPF1.DEF C09SPF2.DEF
-58 0
+58 1 C17SPE2.DEF
 59 1 C09SPF0.DEF
 60 0
 61 0

+ 7 - 9
hch/CDefHandler.cpp

@@ -16,7 +16,6 @@ CDefHandler::CDefHandler()
 {
 	//FDef = NULL;
 	RWEntries = NULL;
-	RLEntries = NULL;
 	notFreeImgs = false;
 }
 CDefHandler::~CDefHandler()
@@ -25,8 +24,6 @@ CDefHandler::~CDefHandler()
 		//delete [] FDef;
 	if (RWEntries)
 		delete [] RWEntries;
-	if (RLEntries)
-		delete [] RLEntries;
 	if (notFreeImgs)
 		return;
 	for (int i=0; i<ourImages.size(); i++)
@@ -47,6 +44,7 @@ void CDefHandler::openDef(std::string name)
 {
 	int i,j, totalInBlock;
 	char Buffer[13];
+	BMPPalette palette[256];
 	defName=name;
 
 	int andame;
@@ -108,7 +106,7 @@ void CDefHandler::openDef(std::string name)
 	for(int i=0; i<SEntries.size(); ++i)
 	{
 		Cimage nimg;
-		nimg.bitmap = getSprite(i, FDef);
+		nimg.bitmap = getSprite(i, FDef, palette);
 		nimg.imName = SEntries[i].name;
 		nimg.groupNumber = SEntries[i].group;
 		ourImages.push_back(nimg);
@@ -121,6 +119,7 @@ void CDefHandler::openFromMemory(unsigned char *table, std::string name)
 {
 	int i,j, totalInBlock;
 	char Buffer[13];
+	BMPPalette palette[256];
 	defName=name;
 	i = 0;
 	DEFType = readNormalNr(i,4,table); i+=4;
@@ -170,11 +169,10 @@ void CDefHandler::openFromMemory(unsigned char *table, std::string name)
 		SEntries[j].name = SEntries[j].name.substr(0, SEntries[j].name.find('.')+4);
 	}
 	RWEntries = new unsigned int[fullHeight];
-	RLEntries = new int[fullHeight];
 	for(int i=0; i<SEntries.size(); ++i)
 	{
 		Cimage nimg;
-		nimg.bitmap = getSprite(i, table);
+		nimg.bitmap = getSprite(i, table, palette);
 		nimg.imName = SEntries[i].name;
 		nimg.groupNumber = SEntries[i].group;
 		ourImages.push_back(nimg);
@@ -241,7 +239,7 @@ void CDefHandler::print (std::ostream & stream, int nr, int bytcon)
 	free(temp);
 }
 
-SDL_Surface * CDefHandler::getSprite (int SIndex, unsigned char * FDef)
+SDL_Surface * CDefHandler::getSprite (int SIndex, unsigned char * FDef, BMPPalette * palette)
 {
 	SDL_Surface * ret=NULL;
 
@@ -341,11 +339,11 @@ SDL_Surface * CDefHandler::getSprite (int SIndex, unsigned char * FDef)
 		}
 		for (int i=0;i<SpriteHeight;i++)
 		{
-			RLEntries[i]=readNormalNr(BaseOffset,4,FDef);BaseOffset+=4;
+			RWEntries[i]=readNormalNr(BaseOffset,4,FDef);BaseOffset+=4;
 		}
 		for (int i=0;i<SpriteHeight;i++)
 		{
-			BaseOffset=BaseOffsetor+RLEntries[i];
+			BaseOffset=BaseOffsetor+RWEntries[i];
 			if (LeftMargin>0)
 			{
 				for (int j=0;j<LeftMargin;j++)

+ 1 - 5
hch/CDefHandler.h

@@ -18,9 +18,7 @@ private:
 	int totalEntries, DEFType, totalBlocks, fullWidth, fullHeight;
 	bool allowRepaint;
 	int length;
-	BMPPalette palette[256];
 	unsigned int * RWEntries;
-	int * RLEntries;
 	struct SEntry
 	{
 		std::string name;
@@ -28,8 +26,6 @@ private:
 		int group;
 	} ;
 	std::vector<SEntry> SEntries ;
-	char id[2];
-
 
 public:
 	static CLodHandler * Spriteh;
@@ -43,7 +39,7 @@ public:
 	static void print (std::ostream & stream, int nr, int bytcon);
 	int readNormalNr (int pos, int bytCon, unsigned char * str=NULL, bool cyclic=false);
 	static unsigned char *writeNormalNr (int nr, int bytCon);
-	SDL_Surface * getSprite (int SIndex, unsigned char * FDef); //zapisuje klatke o zadanym numerze do "testtt.bmp"
+	SDL_Surface * getSprite (int SIndex, unsigned char * FDef, BMPPalette * palette); //zapisuje klatke o zadanym numerze do "testtt.bmp"
 	void openDef(std::string name);
 	void expand(unsigned char N,unsigned char & BL, unsigned char & BR);
 	void openFromMemory(unsigned char * table, std::string name);

+ 28 - 0
hch/CObjectHandler.cpp

@@ -5,6 +5,7 @@
 #include "CLodHandler.h"
 #include "CDefObjInfoHandler.h"
 #include "CHeroHandler.h"
+#include "CSpellHandler.h"
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/random/linear_congruential.hpp>
 #include "CTownHandler.h"
@@ -407,6 +408,33 @@ const CArtifact * CGHeroInstance::getArt(int pos) const
 	else
 		return NULL;
 }
+
+int CGHeroInstance::getSpellSecLevel(int spell) const
+{
+	int bestslvl = 0;
+	if(VLC->spellh->spells[spell].air)
+		if(getSecSkillLevel(15) >= bestslvl)
+		{
+			bestslvl = getSecSkillLevel(15);
+		}
+	if(VLC->spellh->spells[spell].fire)
+		if(getSecSkillLevel(14) >= bestslvl)
+		{
+			bestslvl = getSecSkillLevel(14);
+		}
+	if(VLC->spellh->spells[spell].water)
+		if(getSecSkillLevel(16) >= bestslvl)
+		{
+			bestslvl = getSecSkillLevel(16);
+		}
+	if(VLC->spellh->spells[spell].earth)
+		if(getSecSkillLevel(17) >= bestslvl)
+		{
+			bestslvl = getSecSkillLevel(17);
+		}
+	return bestslvl;
+}
+
 int CGTownInstance::getSightDistance() const //returns sight distance
 {
 	return 10;

+ 1 - 0
hch/CObjectHandler.h

@@ -132,6 +132,7 @@ public:
 	ui32 getArtAtPos(ui16 pos) const; //-1 - no artifact
 	void setArtAtPos(ui16 pos, int art);
 	const CArtifact * getArt(int pos) const;
+	int getSpellSecLevel(int spell) const; //returns level of secondary ability (fire, water, earth, air magic) known to this hero and applicable to given spell; -1 if error
 	void initHero(); 
 	void initHero(int SUBID); 
 	CGHeroInstance();

+ 10 - 0
server/CGameHandler.cpp

@@ -1279,6 +1279,16 @@ upgend:
 									sendAndApply(&sse);
 									break;
 								}
+							case 54: //slow
+								{
+									SetStackEffect sse;
+									sse.stack = gs->curB->getStackT(ba.destinationTile)->ID;
+									sse.effect.id = 54;
+									sse.effect.level = getSchoolLevel(h,s);
+									sse.effect.turnsRemain = h->getPrimSkillLevel(2);
+									sendAndApply(&sse);
+									break;
+								}
 							}
 
 							//TODO: spells to support possibly soon (list by Zamolxis):