From ac7bc76b7b21ddb29114071fc79ed258983cf9c6 Mon Sep 17 00:00:00 2001 From: mateuszb Date: Sun, 7 Mar 2010 17:40:33 +0000 Subject: [PATCH] * implemented first aid kit including first aid secondary ability --- AI/GeniusAI/BattleLogic.cpp | 2 +- client/CBattleInterface.cpp | 29 +++++++++++-- config/cr_abils.txt | 2 +- lib/BattleAction.h | 4 +- lib/CGameState.cpp | 3 +- lib/NetPacksLib.cpp | 2 +- server/CGameHandler.cpp | 81 +++++++++++++++++++++++++++++++++++++ 7 files changed, 114 insertions(+), 9 deletions(-) diff --git a/AI/GeniusAI/BattleLogic.cpp b/AI/GeniusAI/BattleLogic.cpp index 4636d1345..211f50bcb 100644 --- a/AI/GeniusAI/BattleLogic.cpp +++ b/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); } diff --git a/client/CBattleInterface.cpp b/client/CBattleInterface.cpp index 0e4e59c09..9b9ffc77c 100644 --- a/client/CBattleInterface.cpp +++ b/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) diff --git a/config/cr_abils.txt b/config/cr_abils.txt index 93478cf3a..ac84b16d8 100644 --- a/config/cr_abils.txt +++ b/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 diff --git a/lib/BattleAction.h b/lib/BattleAction.h index 56e8dc386..23f231fa7 100644 --- a/lib/BattleAction.h +++ b/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 void serialize(Handler &h, const int version) diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index ce68e1951..596acaaa0 100644 --- a/lib/CGameState.cpp +++ b/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 diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index dbac639ab..d5ececde9 100644 --- a/lib/NetPacksLib.cpp +++ b/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; } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 03c40d433..1d443260c 100644 --- a/server/CGameHandler.cpp +++ b/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; vcurB->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; }