Sfoglia il codice sorgente

Half-done Altar of Sacrifice. (Sacrificing creatures should work)

Michał W. Urbańczyk 15 anni fa
parent
commit
cedf6d812c

+ 1 - 1
client/AdventureMapButton.cpp

@@ -520,7 +520,7 @@ void CSlider::moveTo(int to)
 
 void CSlider::clickLeft(tribool down, bool previousState)
 {
-	if(down)
+	if(down && !slider->blocked)
 	{
 		float pw = 0;
 		float rw = 0;

+ 1 - 1
client/CHeroWindow.cpp

@@ -71,7 +71,7 @@ CHeroWindow::CHeroWindow(int playerColor):
 	curHero = NULL;
 	char bufor[400];
 
-	artifs = new CArtifactsOfHero(pos);
+	artifs = new CArtifactsOfHero(pos.topLeft());
 	artifs->commonInfo = new CArtifactsOfHero::SCommonPart;
 	artifs->commonInfo->participants.insert(artifs);
 

+ 30 - 5
client/CPlayerInterface.cpp

@@ -396,6 +396,13 @@ int3 CPlayerInterface::repairScreenPos(int3 pos)
 }
 void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val)
 {
+	if(which == 4)
+	{
+		if(CAltarWindow *ctw = dynamic_cast<CAltarWindow *>(GH.topInt()))
+		{
+			ctw->setExpToLevel();
+		}
+	}
 	if(which >= PRIMARY_SKILLS) //no need to redraw infowin if this is experience (exp is treated as prim skill with id==4)
 		return;
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
@@ -415,6 +422,9 @@ void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero)
 void CPlayerInterface::receivedResource(int type, int val)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
+	if(CMarketplaceWindow *mw = dynamic_cast<CMarketplaceWindow *>(GH.topInt()))
+		mw->resourceChanged(type, val);
+	
 	GH.totalRedraw();
 }
 
@@ -483,7 +493,7 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
 		 //need to create "Garrison Holder" class thingy
 			cki->updateAllGarrisons();
 		}
-		else if(CMarketplaceWindow *cmw = dynamic_cast<CMarketplaceWindow*>(*i))
+		else if(CTradeWindow *cmw = dynamic_cast<CTradeWindow*>(*i))
 		{
 			if(obj == cmw->hero)
 				cmw->garrisonChanged();
@@ -935,8 +945,7 @@ void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero)
 		adventureInt->heroWindow->activate();
 		return;
 	}
-	CExchangeWindow* cew = dynamic_cast<CExchangeWindow*>(GH.topInt());
-	if(cew) //exchange window is open
+	if(CExchangeWindow* cew = dynamic_cast<CExchangeWindow*>(GH.topInt())) //exchange window is open
 	{
 		cew->deactivate();
 		for(int g=0; g<ARRAY_COUNT(cew->heroInst); ++g)
@@ -951,6 +960,14 @@ void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero)
 		cew->prepareBackground();
 		cew->activate();
 	}
+	else if(CTradeWindow *caw = dynamic_cast<CTradeWindow*>(GH.topInt()))
+	{
+		caw->deactivate();
+		caw->arts->updateState = true;
+		caw->arts->setHero(hero);
+		caw->arts->updateState = false;
+		caw->activate();
+	}
 }
 
 void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town )
@@ -1987,8 +2004,16 @@ void CPlayerInterface::stopMovement()
 
 void CPlayerInterface::showMarketWindow(const IMarket *market, const CGHeroInstance *visitor)
 {
-	CMarketplaceWindow *cmw = new CMarketplaceWindow(market, visitor, market->availableModes().front());
-	GH.pushInt(cmw);
+	if(market->o->ID == 2) //Altar
+	{
+		EMarketMode mode = market->availableModes().front();
+		if(market->allowsTrade(ARTIFACT_EXP) && visitor->getAlignment() != EVIL)
+			GH.pushInt(new CAltarWindow(market, visitor, ARTIFACT_EXP));
+		else if(market->allowsTrade(CREATURE_EXP) && visitor->getAlignment() != GOOD)
+			GH.pushInt(new CAltarWindow(market, visitor, CREATURE_EXP));
+	}
+	else
+		GH.pushInt(new CMarketplaceWindow(market, visitor, market->availableModes().front()));
 }
 
 void CPlayerInterface::availableArtifactsChanged(const CGBlackMarket *bm /*= NULL*/)

File diff suppressed because it is too large
+ 663 - 214
client/GUIClasses.cpp


+ 83 - 48
client/GUIClasses.h

@@ -579,13 +579,12 @@ public:
 	void showAll(SDL_Surface * to);
 };
 
-class CMarketplaceWindow : public CIntObject
+class CTradeWindow : public CIntObject //base for markets and altar of sacrifice
 {
-	bool printButtonFor(EMarketMode M) const;
 public:
 	enum EType
 	{
-		RESOURCE, PLAYER, ARTIFACT, CREATURE
+		RESOURCE, PLAYER, ARTIFACT, CREATURE, CREATURE_PLACEHOLDER,ARTIFACT_PLACEHOLDER
 	};
 	class CTradeableItem : public CIntObject
 	{
@@ -594,9 +593,16 @@ public:
 		int id; 
 		int serial;
 		bool left;
+		std::string subtitle; //empty if default
+
 		CFunctionList<void()> callback;
+		bool downSelection;
 
-		void show(SDL_Surface * to);
+		void showAllAt(const Point &dstPos, const std::string &customSub, SDL_Surface * to);
+
+		void clickRight(tribool down, bool previousState);
+		void hover (bool on);
+		void showAll(SDL_Surface * to);
 		void clickLeft(tribool down, bool previousState);
 		SDL_Surface *getSurface();
 		CTradeableItem(EType Type, int ID, bool Left, int Serial);
@@ -605,30 +611,96 @@ public:
 	const IMarket *market;
 	const CGHeroInstance *hero;
 	CPicture *bg; //background
-	std::vector<CTradeableItem*> left, right;
-	std::vector<std::string> rSubs; //offer caption
+
+	CArtifactsOfHero *arts;
+	//all indexes: 1 = left, 0 = right
+	std::vector<CTradeableItem*> items[2];
 	CTradeableItem *hLeft, *hRight; //highlighted items (NULL if no highlight)
+	EType itemsType[2];
 
-	EType ltype, rtype;
 	EMarketMode mode;//0 - res<->res; 1 - res<->plauer; 2 - buy artifact; 3 - sell artifact
-	int r1, r2; //suggested amounts of traded resources
 	AdventureMapButton *ok, *max, *deal;
 	CSlider *slider; //for choosing amount to be exchanged
 	bool readyToTrade;
 
+	CTradeWindow(const IMarket *Market, const CGHeroInstance *Hero, EMarketMode Mode); //c
+
 	void showAll(SDL_Surface * to);
+
+	void initSubs(bool Left);
+	void initTypes();
+	void initItems(bool Left);
+	std::vector<int> *getItemsIds(bool Left); //NULL if default
+	void getPositionsFor(std::vector<Rect> &poss, bool Left, EType type) const;
+	void removeItems(const std::set<CTradeableItem *> &toRemove);
+	void removeItem(CTradeableItem * t);
+	void getEmptySlots(std::set<CTradeableItem *> &toRemove);
+	void setMode(EMarketMode Mode); //mode setter
+
+	virtual void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const = 0;
+	virtual void selectionChanged(bool side) = 0; //true == left
+	virtual Point selectionOffset(bool Left) const = 0;
+	virtual std::string selectionSubtitle(bool Left) const = 0;
+	virtual void garrisonChanged() = 0; 
+	virtual void artifactsChanged(bool left) = 0;
+};
+
+class CMarketplaceWindow : public CTradeWindow
+{
+	bool printButtonFor(EMarketMode M) const;
+public:
+	int r1, r2; //suggested amounts of traded resources
+
 	void setMax();
 	void sliderMoved(int to);
 	void makeDeal();
 	void selectionChanged(bool side); //true == left
 	CMarketplaceWindow(const IMarket *Market, const CGHeroInstance *Hero = NULL, EMarketMode Mode = RESOURCE_RESOURCE); //c-tor
 	~CMarketplaceWindow(); //d-tor
-	void setMode(EMarketMode Mode); //mode setter
 
-	void getPositionsFor(std::vector<Rect> &poss, bool Right, EType type) const;
+	Point selectionOffset(bool Left) const;
+	std::string selectionSubtitle(bool Left) const;
+
 
 	void garrisonChanged(); //removes creatures with count 0 from the list (apparently whole stack has been sold)
 	void artifactsChanged(bool left);
+	void resourceChanged(int type, int val);
+
+	void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const;
+};
+
+class CAltarWindow : public CTradeWindow
+{
+public:
+	CAltarWindow(const IMarket *Market, const CGHeroInstance *Hero, EMarketMode Mode); //c-tor
+
+	void getExpValues();
+	~CAltarWindow(); //d-tor
+
+	std::vector<int> sacrificedUnits, //[slot_nr] -> how many creatures from that slot will be sacrificed
+		expPerUnit;
+
+	AdventureMapButton *sacrificeAll, *sacrificeBackpack;
+	CLabel *expToLevel, *expOnAltar;
+
+
+	void selectionChanged(bool side); //true == left
+	void SacrificeAll();
+	void SacrificeBackpack();
+	void makeDeal();
+
+	void blockTrade();
+	void sliderMoved(int to);
+	void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const;
+	void mimicCres();
+
+	Point selectionOffset(bool Left) const;
+	std::string selectionSubtitle(bool Left) const;
+	void garrisonChanged(); 
+	void artifactsChanged(bool left);
+	void calcTotalExp();
+	void setExpToLevel();
+	void updateRight(CTradeableItem *toUpdate);
 };
 
 class CSystemOptionsWindow : public CIntObject
@@ -809,12 +881,7 @@ public:
 
 class CArtPlace: public LRClickableAreaWTextComp
 {
-private:
-	bool active;
 public:
-	//bool spellBook, warMachine1, warMachine2, warMachine3, warMachine4,
-	//	misc1, misc2, misc3, misc4, misc5, feet, lRing, rRing, torso,
-	//	lHand, rHand, neck, shoulders, head; //my types
 	ui16 slotID; //0   	head	1 	shoulders		2 	neck		3 	right hand		4 	left hand		5 	torso		6 	right ring		7 	left ring		8 	feet		9 	misc. slot 1		10 	misc. slot 2		11 	misc. slot 3		12 	misc. slot 4		13 	ballista (war machine 1)		14 	ammo cart (war machine 2)		15 	first aid tent (war machine 3)		16 	catapult		17 	spell book		18 	misc. slot 5		19+ 	backpack slots
 
 	bool marked;
@@ -877,7 +944,7 @@ public:
 	void setSlotData (CArtPlace* artPlace, int slotID);
 	void eraseSlotData (CArtPlace* artPlace, int slotID);
 
-	CArtifactsOfHero(const SDL_Rect & position); //c-tor
+	CArtifactsOfHero(const Point& position); //c-tor
 	~CArtifactsOfHero(); //d-tor
 
 	friend class CArtPlace;
@@ -1001,38 +1068,6 @@ public:
 	~CTransformerWindow(); //d-tor
 };
 
-class CShopWindow : public CIntObject
-{
-public:
-	std::map<ui16, Component> available, chosen, bought;
-
-	bool swapItem (ui16 which, bool choose);
-	virtual void Buy() {};
-};
-class CArtMerchantWindow : public CShopWindow
-{
-public:
-	void activate();
-	void deactivate();	
-	void show(SDL_Surface * to);
-	void Buy();
-
-	CArtMerchantWindow();
-	~CArtMerchantWindow();
-};
-class CUniversityWindow : public CShopWindow
-{};
-class CAltarWindow : public CShopWindow
-{};
-class CRefugeeCampWindow : public CShopWindow
-{};
-class CWarMachineWindow : public CShopWindow
-{};
-class CFreelancersWindow : public CShopWindow
-{};
-class CHillFortWindow : public CIntObject //garrison dialog? shop?
-{};
-
 class CThievesGuildWindow : public CIntObject
 {
 	const CGObjectInstance * owner;

+ 1 - 1
config/settings.txt

@@ -3,7 +3,7 @@
 clientSettings
 {
 	port=3030;
-	resolution=1024x768; // format: WxH
+	resolution=800x600; // format: WxH
 	bpp=24; // bytes per pixels: 24 or 32
 	fullscreen=0; //0 - windowed mode, 1 - fullscreen
 	server=127.0.0.1; //use 127.0.0.1 for localhost

+ 7 - 3
global.h

@@ -105,9 +105,9 @@ const int CREEP_SIZE = 4000; // neutral stacks won't grow beyon this number
 const int WEEKLY_GROWTH = 10; //percent
 const int AVAILABLE_HEROES_PER_PLAYER = 2;
 
-#define BFIELD_WIDTH (17)
-#define BFIELD_HEIGHT (11)
-#define BFIELD_SIZE ((BFIELD_WIDTH) * (BFIELD_HEIGHT))
+const int BFIELD_WIDTH = 17;
+const int BFIELD_HEIGHT = 11;
+const int BFIELD_SIZE = BFIELD_WIDTH * BFIELD_HEIGHT;
 
 enum EMarketMode
 {
@@ -116,6 +116,10 @@ enum EMarketMode
 	MARTKET_AFTER_LAST_PLACEHOLDER
 };
 
+enum EAlignment
+{
+	GOOD, EVIL, NEUTRAL
+};
 //uncomment to make it work
 //#define MARK_BLOCKED_POSITIONS
 //#define MARK_VISITABLE_POSITIONS

+ 6 - 0
hch/CHeroHandler.cpp

@@ -47,6 +47,11 @@ int CHeroClass::chooseSecSkill(const std::set<int> & possibles) const //picks se
 	throw std::string("Cannot pick secondary skill!");
 }
 
+EAlignment CHeroClass::getAlignment()
+{
+	return (EAlignment)alignment;
+}
+
 int CObstacleInfo::getWidth() const
 {
 	int ret = 1;
@@ -440,6 +445,7 @@ void CHeroHandler::loadHeroClasses()
 	for(int ss=0; ss<18; ++ss) //18 classes of hero (including conflux)
 	{
 		CHeroClass * hc = new CHeroClass;
+		hc->alignment = ss / 6;
 
 		char name[BUFFER_SIZE+1];
 		str.get(name, BUFFER_SIZE, '\t');

+ 3 - 1
hch/CHeroHandler.h

@@ -54,6 +54,7 @@ public:
 class DLL_EXPORT CHeroClass
 {
 public:
+	ui8 alignment; 
 	ui32 skillLimit; //how many secondary skills can hero learn
 	std::string name;
 	float aggression;
@@ -70,8 +71,9 @@ public:
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & skillLimit & name & aggression & initialAttack & initialDefence & initialPower & initialKnowledge & primChance
-			& proSec & selectionProbability & terrCosts;
+			& proSec & selectionProbability & terrCosts & alignment;
 	}
+EAlignment getAlignment();
 };
 
 struct DLL_EXPORT CObstacleInfo

+ 13 - 0
hch/CObjectHandler.cpp

@@ -1516,6 +1516,11 @@ void CGHeroInstance::getBonuses(BonusList &out, const CSelector &selector, const
 	}
 }
 
+EAlignment CGHeroInstance::getAlignment() const
+{
+	return type->heroClass->getAlignment();
+}
+
 void CGDwelling::initObj()
 {
 	switch(ID)
@@ -2239,6 +2244,7 @@ bool CGTownInstance::allowsTrade(EMarketMode mode) const
 	case RESOURCE_PLAYER:
 		return vstd::contains(builtBuildings, 14); // 	marketplace
 	case ARTIFACT_RESOURCE:
+	case RESOURCE_ARTIFACT:
 		return (subID == 2 || subID == 5 || subID == 8) && vstd::contains(builtBuildings, 17);//artifact merchants
 	case CREATURE_RESOURCE:
 		return subID == 6 && vstd::contains(builtBuildings, 21); //Freelancer's guild
@@ -6488,6 +6494,13 @@ bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode)
 		}
 		break;
 
+	case CREATURE_EXP:
+		{
+			val1 = 1;
+			val2 = (VLC->creh->creatures[id1]->AIValue / 40) * 5;
+		}
+		break;
+
 	default:
 		assert(0);
 		return false;

+ 2 - 1
hch/CObjectHandler.h

@@ -337,7 +337,8 @@ public:
 	void getOutOffsets(std::vector<int3> &offsets) const; //offsets to obj pos when we boat can be placed
 
 	//////////////////////////////////////////////////////////////////////////
-
+	
+	EAlignment getAlignment() const;
 	const std::string &getBiography() const;
 	bool needsLastStack()const;
 	unsigned int getTileCost(const TerrainTile &dest, const TerrainTile &from) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling

+ 28 - 0
server/CGameHandler.cpp

@@ -4866,5 +4866,33 @@ bool CGameHandler::tryAttackingGuard(const int3 &guardPos, const CGHeroInstance
 	const TerrainTile &guardTile = gs->map->terrain[guardPos.x][guardPos.y][guardPos.z];
 	objectVisited(guardTile.visitableObjects.back(), h);
 	visitObjectAfterVictory = true;
+	return true;
+}
+
+bool CGameHandler::sacrificeCreatures(const IMarket *market, const CGHeroInstance *hero, TSlot slot, ui32 count)
+{
+	int oldCount = hero->getAmount(slot);
+	int newCount = oldCount - count;
+
+	if(oldCount < count)
+		COMPLAIN_RET("Not enough creatures to sacrifice!")
+	else if(oldCount == count && hero->Slots().size() == 1 && hero->needsLastStack())
+		COMPLAIN_RET("Cannot sacrifice last creature!");
+
+	int crid = hero->getStack(slot).type->idNumber;
+	
+	SetGarrisons sg;
+	sg.garrs[hero->id] = hero->getArmy();
+	if(newCount)
+		sg.garrs[hero->id].setStackCount(slot, newCount);
+	else
+		sg.garrs[hero->id].eraseStack(slot);
+	sendAndApply(&sg);
+
+	int dump, exp;
+	market->getOffer(crid, 0, dump, exp, CREATURE_EXP);
+	exp *= count;
+	changePrimSkill	(hero->id, 4, exp);
+
 	return true;
 }

+ 1 - 0
server/CGameHandler.h

@@ -171,6 +171,7 @@ public:
 	bool buildBoat( ui32 objid );
 	bool setFormation( si32 hid, ui8 formation );
 	bool tradeResources(const IMarket *market, ui32 val, ui8 player, ui32 id1, ui32 id2);
+	bool sacrificeCreatures(const IMarket *market, const CGHeroInstance *hero, TSlot slot, ui32 count);
 	bool sendResources(ui32 val, ui8 player, ui32 r1, ui32 r2);
 	bool sellCreatures(ui32 count, const IMarket *market, const CGHeroInstance * hero, ui32 slot, ui32 resourceID);
 	bool transformInUndead(const IMarket *market, const CGHeroInstance * hero, ui32 slot);

+ 2 - 0
server/NetPacksServer.cpp

@@ -158,6 +158,8 @@ bool TradeOnMarketplace::applyGh( CGameHandler *gh )
 		return gh->buyArtifact(m, hero, r1, r2);
 	case CREATURE_UNDEAD:
 		return gh->transformInUndead(m, hero, r1);
+	case CREATURE_EXP:
+		return gh->sacrificeCreatures(m, hero, r1, val);
 	default:
 		COMPLAIN_AND_RETURN("Unknown exchange mode!");
 	}

Some files were not shown because too many files changed in this diff