Răsfoiți Sursa

* loading AI dll for neutrals
* hopefully fixed reported by Zamolxis garrison bugs
* fixed calculating hero level
* fixed gicing starting exp for heroes

Michał W. Urbańczyk 17 ani în urmă
părinte
comite
f6807a2af9
9 a modificat fișierele cu 100 adăugiri și 65 ștergeri
  1. 3 10
      CGameInterface.cpp
  2. 12 1
      CPlayerInterface.cpp
  3. 24 0
      ChangeLog
  4. 15 22
      client/Client.cpp
  5. 1 1
      hch/CHeroHandler.cpp
  6. 13 2
      hch/CObjectHandler.cpp
  7. 3 0
      hch/CObjectHandler.h
  8. 1 1
      map.cpp
  9. 28 28
      server/CGameHandler.cpp

+ 3 - 10
CGameInterface.cpp

@@ -24,6 +24,7 @@ using namespace CSDL_Ext;
 
 CGlobalAI * CAIHandler::getNewAI(CCallback * cb, std::string dllname)
 {
+	char temp[50];
 	dllname = "AI/"+dllname;
 	CGlobalAI * ret=NULL;
 	CGlobalAI*(*getAI)();
@@ -34,26 +35,18 @@ CGlobalAI * CAIHandler::getNewAI(CCallback * cb, std::string dllname)
 	if (!dll)
 	{
 		tlog1 << "Cannot open AI library ("<<dllname<<"). Throwing..."<<std::endl;
-	#ifdef _MSC_VER
-		throw new std::exception("Cannot open AI library");
-	#endif
-		throw new std::exception();
+		throw new std::string("Cannot open AI library");
 	}
 	//int len = dllname.size()+1;
 	getName = (void(*)(char*))GetProcAddress(dll,"GetAiName");
 	getAI = (CGlobalAI*(*)())GetProcAddress(dll,"GetNewAI");
+	getName(temp);
 #else
 	; //TODO: handle AI library on Linux
-#endif
-	char * temp = new char[50];
-#if _WIN32
-	getName(temp);
 #endif
 	tlog0 << "Loaded .dll with AI named " << temp << std::endl;
-	delete temp;
 #if _WIN32
 	ret = getAI();
-	ret->init(cb);
 #else
 	//ret = new CEmptyAI();
 #endif

+ 12 - 1
CPlayerInterface.cpp

@@ -124,8 +124,19 @@ void CGarrisonSlot::hover (bool on)
 		{
 			if(owner->highlighted)
 			{
+				const CArmedInstance *highl = owner->highlighted->getObj(); 
+				if(  highl->needsLastStack()		//we are moving stack from hero's
+				  && highl->army.slots.size() == 1	//it's only stack
+				  && owner->highlighted->upg != upg	//we're moving it to the other garrison
+				  )
+				{
+					temp = CGI->townh->tcommands[5]; //cannot move last stack!
+				}
+				else
+				{
 					temp = CGI->townh->tcommands[6];
 					boost::algorithm::replace_first(temp,"%s",owner->highlighted->creature->nameSing);
+				}
 			}
 			else
 			{
@@ -1935,7 +1946,7 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
 			hw->garInt->recreateSlots();
 			hw->garInt->show();
 		}
-		if(castleInt) //opened town window - redraw town garrsion slots (change is within hero garr)
+		if(castleInt) //opened town window - redraw town garrison slots (change is within hero garr)
 		{
 			castleInt->garr->highlighted = NULL;
 			castleInt->garr->recreateSlots();

+ 24 - 0
ChangeLog

@@ -1,3 +1,27 @@
+0.64 -> 0.next (???)  [as for r639]
+GENERAL:
+* move some settings to the config/settings.txt file
+* partial support for new screen resolutions
+* /Data and /Sprites subfolders can be used for adding files not present in .lod archives 
+* fixed crashbug occuring when hero levelled above 15 level
+
+BATTLES
+* magic arrow *really* works
+* war machines support partially added
+* queue of stacks narrowed
+* spell effect animation displaying improvements
+* several reported bugs fixed
+* new spells supported:
+	a) Haste 
+	b) lightning bolt 
+	c) ice bolt
+	d) slow 
+	e) implosion
+
+GENERAL:
+* started making external settings file (will be used for support for non 800x600 screen resolutions) 
+And a lot of minor fixes
+
 0.63 -> 0.64 (Nov 01 2008)
 GENERAL:
 * sprites from /Sprites folder are handled correctly

+ 15 - 22
client/Client.cpp

@@ -110,9 +110,11 @@ CClient::CClient(CConnection *con, StartInfo *si)
 	c << *si;
 	c >> pom8;
 	if(pom8) throw "Server cannot open the map!";
-	c << ui8(si->playerInfos.size());
+	c << ui8(si->playerInfos.size()+1); //number of players + neutral
 	for(int i=0;i<si->playerInfos.size();i++)
-		c << ui8(si->playerInfos[i].color);
+		c << ui8(si->playerInfos[i].color); //players
+	c << ui8(255); // neutrals
+
 
 	ui32 seed, sum;
 	std::string mapname;
@@ -142,21 +144,20 @@ CClient::CClient(CConnection *con, StartInfo *si)
 	CGI->mh->init();
 	tlog0 <<"Initializing mapHandler (together): "<<tmh.getDif()<<std::endl;
 
-	for (int i=0; i<CGI->state->scenarioOps->playerInfos.size();i++) //initializing interfaces
+	for (int i=0; i<CGI->state->scenarioOps->playerInfos.size();i++) //initializing interfaces for players
 	{ 
 		ui8 color = gs->scenarioOps->playerInfos[i].color;
 		CCallback *cb = new CCallback(gs,color,this);
 		if(!gs->scenarioOps->playerInfos[i].human)
-		{
 			playerint[color] = static_cast<CGameInterface*>(CAIHandler::getNewAI(cb,conf.cc.defaultAI));
-		}
 		else 
-		{
-			gs->currentPlayer = color;
 			playerint[color] = new CPlayerInterface(color,i);
-			playerint[color]->init(cb);
-		}
+		gs->currentPlayer = color;
+		playerint[color]->init(cb);
 	}
+	playerint[255] =  CAIHandler::getNewAI(cb,conf.cc.defaultAI);
+	playerint[255]->init(new CCallback(gs,255,this));
+
 }
 CClient::~CClient(void)
 {
@@ -166,11 +167,12 @@ void CClient::process(int what)
 	static BattleAction curbaction;
 	switch (what)
 	{
-	case 100: //one of our interaces has turn
+	case 100: //one of our interfaces has turn
 		{
 			ui8 player;
 			*serv >> player;//who?
 			tlog5 << "It's turn of "<<(unsigned)player<<" player."<<std::endl;
+			gs->currentPlayer = player;
 			boost::thread(boost::bind(&CGameInterface::yourTurn,playerint[player]));
 			break;
 		}
@@ -343,9 +345,10 @@ void CClient::process(int what)
 				//std::for_each(th->fowRevealed.begin(),th->fowRevealed.end(),boost::bind(&CGameInterface::tileRevealed,playerint[player],_1));
 			}
 
-			//notify interfacesabout move
+			//notify interfaces about move
 			for(std::map<ui8, CGameInterface*>::iterator i=playerint.begin();i!=playerint.end();i++)
 			{
+				if(i->first >= PLAYER_LIMIT) continue;
 				if(gs->players[i->first].fogOfWarMap[th->start.x-1][th->start.y][th->start.z] || gs->players[i->first].fogOfWarMap[th->end.x-1][th->end.y][th->end.z])
 				{
 					i->second->heroMoved(hmd);
@@ -546,17 +549,7 @@ void CClient::process(int what)
 			tlog5 << "Active stack: " << sas.stack <<std::endl;
 			gs->apply(&sas);
 			int owner = gs->curB->getStack(sas.stack)->owner;
-			if(owner >= PLAYER_LIMIT) //ugly workaround to skip neutral creatures - should be replaced with AI
-			{
-				BattleAction ba;
-				ba.stackNumber = sas.stack;
-				ba.actionType = 3;
-				*serv << ui16(3002) << ba;
-			}
-			else
-			{
-				boost::thread(boost::bind(&CClient::waitForMoveAndSend,this,owner));
-			}
+			boost::thread(boost::bind(&CClient::waitForMoveAndSend,this,owner));
 			break;
 		}
 	case 3003:

+ 1 - 1
hch/CHeroHandler.cpp

@@ -338,7 +338,7 @@ unsigned int CHeroHandler::level(unsigned int experience)
 	for(int i=expPerLevel.size()-1; i>=0; --i)
 	{
 		if(experience>=expPerLevel[i])
-			return i+add;
+			return 1+i+add;
 	}
 	return -1;
 }

+ 13 - 2
hch/CObjectHandler.cpp

@@ -561,7 +561,7 @@ CGHeroInstance::CGHeroInstance()
 	mana = movement = portrait = level = -1;
 	isStanding = true;
 	moveDir = 4;
-	exp = 0;
+	exp = 0xffffffff;
 	visitedTown = NULL;
 	type = NULL;
 	secSkills.push_back(std::make_pair(-1, -1));
@@ -618,7 +618,7 @@ void CGHeroInstance::initHero()
 		name = type->name;
 	if (!biography.length())
 		biography = type->biography;		
-	if (exp == -1)
+	if (exp == 0xffffffff)
 	{
 		exp=40+  (ran())  % 50;
 		level = 1;
@@ -662,6 +662,10 @@ CGHeroInstance::~CGHeroInstance()
 {
 }
 
+bool CGHeroInstance::needsLastStack() const
+{
+	return true;
+}
 CGTownInstance::~CGTownInstance()
 {}
 
@@ -674,6 +678,13 @@ int CGTownInstance::spellsAtLevel(int level, bool checkGuild) const
 		ret++; 
 	return ret;
 }
+
+bool CGTownInstance::needsLastStack() const
+{
+	if(garrisonHero)
+		return true;
+	else return false;
+}
 CGObjectInstance::CGObjectInstance(const CGObjectInstance & right)
 {
 	pos = right.pos;

+ 3 - 0
hch/CObjectHandler.h

@@ -75,6 +75,7 @@ class  DLL_EXPORT CArmedInstance: public CGObjectInstance
 {
 public:
 	CCreatureSet army; //army
+	virtual bool needsLastStack() const=0; //true if last stack cannot be taken
 };
 
 class DLL_EXPORT CGHeroInstance : public CArmedInstance
@@ -112,6 +113,7 @@ public:
 	std::map<ui16,ui32> artifWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
 	std::set<ui32> spells; //known spells (spell IDs)
 
+	bool needsLastStack()const;
 	virtual bool isHero() const;
 	unsigned int getTileCost(const EterrainType & ttype, const Eroad & rdtype, const Eriver & rvtype) const;
 	unsigned int getLowestCreatureSpeed();
@@ -165,6 +167,7 @@ public:
 	std::set<CCastleEvent> events;
 
 
+	bool needsLastStack() const;
 	int getSightDistance() const; //returns sight distance
 	int fortLevel() const; //0 - none, 1 - fort, 2 - citadel, 3 - castle
 	int hallLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol

+ 1 - 1
map.cpp

@@ -1054,7 +1054,7 @@ void Mapa::loadHero( CGObjectInstance * &nobj, unsigned char * bufor, int &i )
 		if(readChar(bufor,i))//true if hore's experience is greater than 0
 		{	nhi->exp = readNormalNr(bufor,i); i+=4;	}
 		else
-			nhi->exp = -1;
+			nhi->exp = 0xffffffff;
 	}
 	else
 	{	nhi->exp = readNormalNr(bufor,i); i+=4;	}

+ 28 - 28
server/CGameHandler.cpp

@@ -518,50 +518,50 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 					c >> what >> id1 >> p1 >> id2 >> p2;
 					CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id1]),
 						*s2 = static_cast<CArmedInstance*>(gs->map->objects[id2]);
-					CCreatureSet *S1 = &s1->army, *S2 = &s2->army;
+					CCreatureSet temp1 = s1->army, temp2 = s2->army,
+						&S1 = temp1, &S2 = (s1!=s2)?(temp2):(temp1);
 					
 					if(what==1) //swap
 					{
-						int pom = S2->slots[p2].first;
-						S2->slots[p2].first = S1->slots[p1].first;
-						S1->slots[p1].first = pom;
-						int pom2 = S2->slots[p2].second;
-						S2->slots[p2].second = S1->slots[p1].second;
-						S1->slots[p1].second = pom2;
-
-						if(!S1->slots[p1].second)
-							S1->slots.erase(p1);
-						if(!S2->slots[p2].second)
-							S2->slots.erase(p2);
+						std::swap(S1.slots[p1],S2.slots[p2]);
+
+						if(!S1.slots[p1].second)
+							S1.slots.erase(p1);
+						if(!S2.slots[p2].second)
+							S2.slots.erase(p2);
 					}
 					else if(what==2)//merge
 					{
-						if(S1->slots[p1].first != S2->slots[p2].first) break; //not same creature
-						S2->slots[p2].second += S1->slots[p1].second;
-						S1->slots[p1].first = NULL;
-						S1->slots[p1].second = 0;
-						S1->slots.erase(p1);
+						if(S1.slots[p1].first != S2.slots[p2].first) break; //not same creature
+						S2.slots[p2].second += S1.slots[p1].second;
+						S1.slots.erase(p1);
 					}
 					else if(what==3) //split
 					{
 						si32 val;
 						c >> val;
-						if(S2->slots.find(p2) != S2->slots.end()) break; //slot not free
-						S2->slots[p2].first = S1->slots[p1].first;
-						S2->slots[p2].second = val;
-						S1->slots[p1].second -= val;
-						if(!S1->slots[p1].second) //if we've moved all creatures
-							S1->slots.erase(p1); 
+						if(	vstd::contains(S2.slots,p2)		//dest. slot not free
+						  || !vstd::contains(S1.slots,p1)	//no creatures to split
+						  || S1.slots[p1].second < val		//not enough creatures
+						  || val<1							//val must be positive
+						) 
+							break; 
+						S2.slots[p2].first = S1.slots[p1].first;
+						S2.slots[p2].second = val;
+						S1.slots[p1].second -= val;
+						if(!S1.slots[p1].second) //if we've moved all creatures
+							S1.slots.erase(p1); 
 					}
-					if((s1->ID==34 && !S1->slots.size()) //it's not allowed to take last stack from hero army!
-						|| (s2->ID==34 && !S2->slots.size()))
+					if((s1->needsLastStack() && !S1.slots.size()) //it's not allowed to take last stack from hero army!
+					  || (s2->needsLastStack() && !S2.slots.size())
+					)
 					{
-						break;
+						break; //leave without applying changes to garrison
 					}
 					SetGarrisons sg;
-					sg.garrs[id1] = *S1;
+					sg.garrs[id1] = S1;
 					if(s1 != s2)
-						sg.garrs[id2] = *S2;
+						sg.garrs[id2] = S2;
 					sendAndApply(&sg);
 					break;
 				}