mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	* implemented first aid kit including first aid secondary ability
This commit is contained in:
		| @@ -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); | ||||
| 	} | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
| 	} | ||||
|   | ||||
| @@ -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; | ||||
| 		} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user