فهرست منبع

* implemented first aid kit including first aid secondary ability

mateuszb 15 سال پیش
والد
کامیت
ac7bc76b7b
7فایلهای تغییر یافته به همراه114 افزوده شده و 9 حذف شده
  1. 1 1
      AI/GeniusAI/BattleLogic.cpp
  2. 25 4
      client/CBattleInterface.cpp
  3. 1 1
      config/cr_abils.txt
  4. 3 1
      lib/BattleAction.h
  5. 2 1
      lib/CGameState.cpp
  6. 1 1
      lib/NetPacksLib.cpp
  7. 81 0
      server/CGameHandler.cpp

+ 1 - 1
AI/GeniusAI/BattleLogic.cpp

@@ -258,7 +258,7 @@ void CBattleLogic::MakeStatistics(int currentCreatureId)
 BattleAction CBattleLogic::MakeDecision(int stackID)
 {
 	const CStack *currentStack = m_cb->battleGetStackByID(stackID);
-	if(currentStack->position < 0) //turret
+	if(currentStack->position < 0 || currentStack->creature->idNumber == 147) //turret or first aid kit
 	{
 		return MakeDefend(stackID);
 	}

+ 25 - 4
client/CBattleInterface.cpp

@@ -1728,7 +1728,16 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 				{
 					if(shere->owner == curInt->playerID) //our stack
 					{
-						CGI->curh->changeGraphic(1,5);
+						if(sactive->hasFeatureOfType(StackFeature::HEALER))
+						{
+							//display the possibility to heal this creature
+							CGI->curh->changeGraphic(1,17);
+						}
+						else
+						{
+							//info about creature
+							CGI->curh->changeGraphic(1,5);
+						}
 						//setting console text
 						char buf[500];
 						sprintf(buf, CGI->generaltexth->allTexts[297].c_str(), shere->amount == 1 ? shere->creature->nameSing.c_str() : shere->creature->namePl.c_str());
@@ -1739,6 +1748,7 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 						{
 							creAnims[shere->ID]->playOnce(1);
 						}
+						
 					}
 					else if(curInt->cb->battleCanShoot(activeStack,myNumber)) //we can shoot enemy
 					{
@@ -2336,7 +2346,6 @@ void CBattleInterface::hexLclicked(int whichOne)
 			const CStack* dest = curInt->cb->battleGetStackByPos(whichOne); //creature at destination tile; -1 if there is no one
 			if(!dest || !dest->alive()) //no creature at that tile
 			{
-				const CStack * sactive = curInt->cb->battleGetStackByID(activeStack);
 				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
@@ -2354,7 +2363,7 @@ void CBattleInterface::hexLclicked(int whichOne)
 						giveCommand(2,whichOne,activeStack);
 					}
 				}
-				else if(sactive->hasFeatureOfType(StackFeature::CATAPULT) && isCatapultAttackable(whichOne)) //attacking (catapult)
+				else if(actSt->hasFeatureOfType(StackFeature::CATAPULT) && isCatapultAttackable(whichOne)) //attacking (catapult)
 				{
 					giveCommand(9,whichOne,activeStack);
 				}
@@ -2519,6 +2528,12 @@ void CBattleInterface::hexLclicked(int whichOne)
 				}
 
 			}
+			else if (actSt->hasFeatureOfType(StackFeature::HEALER) && actSt->owner == dest->owner) //friendly creature we can heal
+			{
+				giveCommand(12, whichOne, activeStack); //command healing
+
+				CGI->curh->changeGraphic(1, 6); //cursor should be changed
+			}
 		}
 	}
 }
@@ -3162,7 +3177,7 @@ void CBattleInterface::startAction(const BattleAction* action)
 
 	char txt[400];
 
-	if(action->actionType == 1)
+	if(action->actionType == 1) //when hero casts spell
 	{
 		if(action->side)
 			defendingHero->setPhase(4);
@@ -3201,6 +3216,12 @@ void CBattleInterface::startAction(const BattleAction* action)
 		sprintf(txt, CGI->generaltexth->allTexts[txtid].c_str(),  (stack->amount != 1) ? stack->creature->namePl.c_str() : stack->creature->nameSing.c_str(), 0);
 		console->addText(txt);
 	}
+
+	//displaying heal animation
+	if (action->actionType == 12)
+	{
+		displayEffect(50, action->destinationTile);
+	}
 }
 
 void CBattleHero::show(SDL_Surface *to)

+ 1 - 1
config/cr_abils.txt

@@ -164,7 +164,7 @@
 + 140 DOUBLE_WIDE 0 0 0 			//boar should be treated as double-wide
 + 142 DOUBLE_WIDE 0 0 0 			//nomads should be treated as double-wide
 + 144 FULL_HP_REGENERATION 0 0 0 			//troll
-+ 147 NOT_ACTIVE 0 0 0	   	 		//First Aid Tent //TODO: remove when support is added
++ 147 HEALER 0 0 0					//first aid tent can heal
 + 148 NOT_ACTIVE 0 0 0				//Ammo Cart
 + 149 SHOOTER 0 0 0					//arrow turret
 -  46 FLYING		  				//hell hound doesn't fly

+ 3 - 1
lib/BattleAction.h

@@ -15,7 +15,9 @@ struct BattleAction
 {
 	ui8 side; //who made this action: false - left, true - right player
 	ui32 stackNumber;//stack ID, -1 left hero, -2 right hero,
-	ui8 actionType; //    0 = No action;   1 = Hero cast a spell   2 = Walk   3 = Defend   4 = Retreat from the battle   5 = Surrender   6 = Walk and Attack   7 = Shoot    8 = Wait   9 = Catapult 10 = Monster casts a spell (i.e. Faerie Dragons)	11 - Bad morale freeze
+	ui8 actionType; //    0 = No action;   1 = Hero cast a spell   2 = Walk   3 = Defend   4 = Retreat from the battle
+		//5 = Surrender   6 = Walk and Attack   7 = Shoot    8 = Wait   9 = Catapult
+		//10 = Monster casts a spell (i.e. Faerie Dragons)	11 - Bad morale freeze	12 - stacks heals another stack
 	ui16 destinationTile;
 	si32 additionalInfo; // e.g. spell number if type is 1 || 10; tile to attack if type is 6
 	template <typename Handler> void serialize(Handler &h, const int version)

+ 2 - 1
lib/CGameState.cpp

@@ -3489,7 +3489,8 @@ si8 BattleInfo::Morale( const CStack * st ) const
 {
 	si8 ret = st->morale;
 
-	if(st->hasFeatureOfType(StackFeature::NON_LIVING) || st->hasFeatureOfType(StackFeature::UNDEAD) || st->hasFeatureOfType(StackFeature::NO_MORALE))
+	if(st->hasFeatureOfType(StackFeature::NON_LIVING) || st->hasFeatureOfType(StackFeature::UNDEAD) ||
+		st->hasFeatureOfType(StackFeature::NO_MORALE) || st->hasFeatureOfType(StackFeature::SIEGE_WEAPON))
 		return 0;
 
 	ret += st->valOfFeatures(StackFeature::MORALE_BONUS); //mirth & sorrow & other

+ 1 - 1
lib/NetPacksLib.cpp

@@ -812,7 +812,7 @@ DLL_EXPORT void StartAction::applyGs( CGameState *gs )
 	case 8:
 		st->state.insert(WAITING);
 		return;
-	case 2: case 6: case 7: case 9: case 10: case 11:
+	case 0: case 2: case 6: case 7: case 9: case 10: case 11: case 12:
 		st->state.insert(MOVED);
 		break;
 	}

+ 81 - 0
server/CGameHandler.cpp

@@ -437,6 +437,49 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
 				continue;
 			}
 
+			if(next->creature->idNumber == 147 && (!curOwner || curOwner->getSecSkillLevel(27) == 0)) //first aid tent, hero has no first aid
+			{
+				BattleAction heal;
+
+				std::vector< const CStack * > possibleStacks;
+				for (int v=0; v<gs->curB->stacks.size(); ++v)
+				{
+					const CStack * cstack = gs->curB->stacks[v];
+					if (cstack->owner == next->owner && cstack->firstHPleft < cstack->MaxHealth() && cstack->alive()) //it's friendly and not fully healthy
+					{
+						possibleStacks.push_back(cstack);
+					}
+				}
+
+				if(possibleStacks.size() == 0)
+				{
+					//nothing to heal
+					BattleAction doNothing;
+					doNothing.actionType = 0;
+					doNothing.additionalInfo = 0;
+					doNothing.destinationTile = -1;
+					doNothing.side = !next->attackerOwned;
+					doNothing.stackNumber = next->ID;
+					sendAndApply(&StartAction(doNothing));
+					sendAndApply(&EndAction());
+					continue;
+				}
+				else
+				{
+					//heal random creature
+					const CStack * toBeHealed = possibleStacks[ rand()%possibleStacks.size() ];
+					heal.actionType = 12;
+					heal.additionalInfo = 0;
+					heal.destinationTile = toBeHealed->position;
+					heal.side = !next->attackerOwned;
+					heal.stackNumber = next->ID;
+
+					makeBattleAction(heal);
+
+				}
+				continue;
+			}
+
 askInterfaceForMove:
 			//ask interface and wait for answer
 			if(!battleResult.get())
@@ -3210,6 +3253,44 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
 
 				sendAndApply(&ca);
 			}
+			sendAndApply(&EndAction());
+			break;
+		}
+	case 12: //healing
+		{
+			static const int healingPerLevel[] = {50, 50, 75, 100};
+			sendAndApply(&StartAction(ba));
+			const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
+			CStack *healer = gs->curB->getStack(ba.stackNumber),
+				*destStack = gs->curB->getStackT(ba.destinationTile);
+
+			if(healer == NULL || destStack == NULL || !healer->hasFeatureOfType(StackFeature::HEALER))
+			{
+				complain("There is either no healer, no destination, or healer cannot heal :P");
+			}
+			int maxHealable = destStack->MaxHealth() - destStack->firstHPleft;
+			int maxiumHeal = healingPerLevel[ attackingHero->getSecSkillLevel(27) ];
+
+			int healed = std::min(maxHealable, maxiumHeal);
+
+			if(healed == 0)
+			{
+				//nothing to heal.. should we complain?
+			}
+			else
+			{
+				StacksHealedOrResurrected shr;
+				StacksHealedOrResurrected::HealInfo hi;
+
+				hi.healedHP = healed;
+				hi.lowLevelResurrection = 0;
+				hi.stackID = destStack->ID;
+
+				shr.healedStacks.push_back(hi);
+				sendAndApply(&shr);
+			}
+
+
 			sendAndApply(&EndAction());
 			break;
 		}