1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-27 22:49:25 +02:00

* fixed project files for RD configuration

* fixed crash when creature is casting Hypnosis (ie. exped Vampire Lords)
* fixed crash when creature is casting Cure before attack (ie. exped Unicorns)
* fixed crash when creature is summoning elemental (TODO fix it)
* fixed crash when doing a bonus system operation with a hero liberated from prison (ie. entering town or battle)
* fixed deadlock when StupidAI tried to assault the turrets
* fixed never ending siege when StupidAI has to use catapult (no more deadlocks on AI-AI siege)
* fixed deadlock when a hero received a level during another player's turn (ie. when he successfully defended)
* AI can win the game by defeating all enemies if there is a specific victory condition applying only to human players
* added options to help testing adventure map AI (--onlyAI, --autoSkip and --oneGoodAI).
* many minor changes
This commit is contained in:
Michał W. Urbańczyk
2012-01-03 01:55:26 +00:00
parent 91c0ce33f4
commit 046e54563c
35 changed files with 305 additions and 107 deletions

View File

@@ -53,6 +53,7 @@ extern bool end2;
#define COMPLAIN_RET_IF(cond, txt) do {if(cond){complain(txt); return;}} while(0)
#define COMPLAIN_RET(txt) {complain(txt); return false;}
#define COMPLAIN_RETF(txt, FORMAT) {complain(boost::str(boost::format(txt) % FORMAT)); return false;}
#define NEW_ROUND BattleNextRound bnr;\
bnr.round = gs->curB->round + 1;\
sendAndApply(&bnr);
@@ -67,7 +68,7 @@ template <typename T> class CApplyOnGH;
class CBaseForGHApply
{
public:
virtual bool applyOnGH(CGameHandler *gh, CConnection *c, void *pack) const =0;
virtual bool applyOnGH(CGameHandler *gh, CConnection *c, void *pack, ui8 player) const =0;
virtual ~CBaseForGHApply(){}
template<typename U> static CBaseForGHApply *getApplier(const U * t=NULL)
{
@@ -78,10 +79,11 @@ public:
template <typename T> class CApplyOnGH : public CBaseForGHApply
{
public:
bool applyOnGH(CGameHandler *gh, CConnection *c, void *pack) const
bool applyOnGH(CGameHandler *gh, CConnection *c, void *pack, ui8 player) const
{
T *ptr = static_cast<T*>(pack);
ptr->c = c;
ptr->player = player;
return ptr->applyGh(gh);
}
};
@@ -121,7 +123,8 @@ void PlayerStatuses::addPlayer(ui8 player)
boost::unique_lock<boost::mutex> l(mx);
players[player];
}
bool PlayerStatuses::hasQueries(ui8 player)
int PlayerStatuses::getQueriesCount(ui8 player)
{
boost::unique_lock<boost::mutex> l(mx);
if(players.find(player) != players.end())
@@ -130,9 +133,10 @@ bool PlayerStatuses::hasQueries(ui8 player)
}
else
{
throw std::string("No such player!");
return 0;
}
}
bool PlayerStatuses::checkFlag(ui8 player, bool PlayerStatus::*flag)
{
boost::unique_lock<boost::mutex> l(mx);
@@ -624,24 +628,26 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
setThreadName(-1, "CGameHandler::handleConnection");
srand(time(NULL));
CPack *pack = NULL;
ui8 player = 255;
try
{
while(1)//server should never shut connection first //was: while(!end2)
{
{
boost::unique_lock<boost::mutex> lock(*c.rmx);
c >> pack; //get the package
c >> player >> pack; //get the package
tlog5 << "Received client message of type " << typeid(*pack).name() << std::endl;
}
int packType = typeList.getTypeID(pack); //get the id of type
CBaseForGHApply *apply = applier->apps[packType]; //and appropriae applier object
if(packType != typeList.getTypeID<QueryReply>() &&
(packType != typeList.getTypeID<ArrangeStacks>() || !isAllowedArrangePack((ArrangeStacks*)pack)) && // for dialogs like garrison
states[getCurrentPlayer()].queries.size())
if(packType != typeList.getTypeID<QueryReply>()
&& (packType != typeList.getTypeID<ArrangeStacks>() || !isAllowedArrangePack((ArrangeStacks*)pack)) // for dialogs like garrison
&& states.getQueriesCount(player))
{
complain("Answer the query before attempting any further actions!");
complain(boost::str(boost::format("Player %d has to answer queries before attempting any further actions (count=%d)!") % (int)player % states.getQueriesCount(player)));
PackageApplied applied;
applied.player = player;
applied.result = false;
applied.packType = packType;
{
@@ -651,11 +657,12 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
}
else if(apply)
{
bool result = apply->applyOnGH(this,&c,pack);
bool result = apply->applyOnGH(this,&c,pack, player);
tlog5 << "Message successfully applied (result=" << result << ")!\n";
//send confirmation that we've applied the package
PackageApplied applied;
applied.player = player;
applied.result = result;
applied.packType = packType;
{
@@ -669,6 +676,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
}
delete pack;
pack = NULL;
player = 255;
}
}
catch(boost::system::system_error &e) //for boost errors just log, not crash - probably client shut down connection
@@ -3544,7 +3552,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
}
//checking if creatures resist
sc.resisted = gs->curB->calculateResistedStacks(spell, caster, secHero, attackedCres, casterColor, mode);
sc.resisted = gs->curB->calculateResistedStacks(spell, caster, secHero, attackedCres, casterColor, mode, usedSpellPower, spellLvl);
//calculating dmg to display
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
@@ -3775,7 +3783,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
hi.healedHP = gs->curB->calculateHealedHP(hpGained, spell, *it);
}
else
hi.healedHP = gs->curB->calculateHealedHP(spell, usedSpellPower, stack->getBonus(Selector::typeSubtype(Bonus::SPELLCASTER, spell->id))->additionalInfo, *it);
hi.healedHP = gs->curB->calculateHealedHP(spell, usedSpellPower, spellLvl, *it);
}
else
hi.healedHP = gs->curB->calculateHealedHP(caster, spell, *it);
@@ -3809,16 +3817,20 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
}
BattleStackAdded bsa;
bsa.pos = gs->curB->getAvaliableHex(creID, !(bool)casterSide); //TODO: unify it
bsa.amount = caster->getPrimSkillLevel(2) * VLC->spellh->spells[spellID]->powers[spellLvl] *
(100 + caster->valOfBonuses(Bonus::SPECIFIC_SPELL_DAMAGE, spellID)) / 100.0; //new feature - percentage bonus
bsa.creID = creID;
bsa.attacker = !(bool)casterSide;
bsa.summoned = true;
sendAndApply(&bsa);
bsa.pos = gs->curB->getAvaliableHex(creID, !(bool)casterSide); //TODO: unify it
//TODO stack casting -> probably power will be zero; set the proper number of creatures manually
int percentBonus = caster ? caster->valOfBonuses(Bonus::SPECIFIC_SPELL_DAMAGE, spellID) : 0;
bsa.amount = usedSpellPower * VLC->spellh->spells[spellID]->powers[spellLvl] *
(100 + percentBonus) / 100.0; //new feature - percentage bonus
if(bsa.amount)
sendAndApply(&bsa);
else
complain("Summoning elementals didn't summon any!");
}
break;
case Spells::REMOVE_OBSTACLE:
@@ -4605,18 +4617,17 @@ bool CGameHandler::dig( const CGHeroInstance *h )
}
}
if(h->diggingStatus() != CGHeroInstance::CAN_DIG) //checks for terrain and movement
COMPLAIN_RETF("Hero cannot dig (error code %d)!", h->diggingStatus());
//create a hole
NewObject no;
no.ID = 124;
no.pos = h->getPosition();
no.subID = getTile(no.pos)->tertype;
if(no.subID >= 8) //no digging on water / rock
{
complain("Cannot dig - wrong terrain type!");
return false;
}
sendAndApply(&no);
//take MPs
SetMovePoints smp;
smp.hid = h->id;
smp.val = 0;