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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user