1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

* amounts of units taking actions / being an object of actions won't be shown until action ends

* provisional support for "Save" button in System Options Window
* forbidden buildings will be shown as forbidden, even if there are no res / other conditions are not fulfilled
* improved damage calculation formula
* several minor improvements
This commit is contained in:
Michał W. Urbańczyk 2009-03-28 00:38:48 +00:00
parent cebd5db8b2
commit 42773e67f2
13 changed files with 128 additions and 63 deletions

View File

@ -485,19 +485,22 @@ void CBattleInterface::show(SDL_Surface * to)
{
for(size_t v=0; v<stackAliveByHex[b].size(); ++v)
{
int animType = creAnims[stackAliveByHex[b][v]]->getType();
int curStackID = stackAliveByHex[b][v];
const CStack &curStack = stacks[curStackID];
int animType = creAnims[curStackID]->getType();
bool incrementFrame = (animCount%(4/animSpeed)==0) && animType!=5 && animType!=20 && animType!=3 && animType!=2;
if(animType == 2)
{
if(standingFrame.find(stackAliveByHex[b][v])!=standingFrame.end())
if(standingFrame.find(curStackID)!=standingFrame.end())
{
incrementFrame = (animCount%(8/animSpeed)==0);
if(incrementFrame)
{
++standingFrame[stackAliveByHex[b][v]];
if(standingFrame[stackAliveByHex[b][v]] == creAnims[stackAliveByHex[b][v]]->framesInGroup(2))
++standingFrame[curStackID];
if(standingFrame[curStackID] == creAnims[curStackID]->framesInGroup(2))
{
standingFrame.erase(standingFrame.find(stackAliveByHex[b][v]));
standingFrame.erase(standingFrame.find(curStackID));
}
}
}
@ -505,29 +508,36 @@ void CBattleInterface::show(SDL_Surface * to)
{
if((rand()%50) == 0)
{
standingFrame.insert(std::make_pair(stackAliveByHex[b][v], 0));
standingFrame.insert(std::make_pair(curStackID, 0));
}
}
}
creAnims[stackAliveByHex[b][v]]->nextFrame(to, creAnims[stackAliveByHex[b][v]]->pos.x + pos.x, creAnims[stackAliveByHex[b][v]]->pos.y + pos.y, creDir[stackAliveByHex[b][v]], animCount, incrementFrame, stackAliveByHex[b][v]==activeStack, stackAliveByHex[b][v]==mouseHoveredStack); //increment always when moving, never if stack died
creAnims[curStackID]->nextFrame(to, creAnims[curStackID]->pos.x + pos.x, creAnims[curStackID]->pos.y + pos.y, creDir[curStackID], animCount, incrementFrame, curStackID==activeStack, curStackID==mouseHoveredStack); //increment always when moving, never if stack died
//printing amount
if(stacks[stackAliveByHex[b][v]].amount > 0) //don't print if stack is not alive
if(curStack.amount > 0 //don't print if stack is not alive
&& !LOCPLINT->curAction
|| (LOCPLINT->curAction->stackNumber != curStackID //don't print if stack is currently taking an action
&& (LOCPLINT->curAction->actionType != 6 || curStack.position != LOCPLINT->curAction->additionalInfo) //nor if it's an object of attack
&& (LOCPLINT->curAction->destinationTile != curStack.position) //nor if it's on destination tile for current action
)
)
{
int xAdd = stacks[stackAliveByHex[b][v]].attackerOwned ? 220 : 202;
int xAdd = curStack.attackerOwned ? 220 : 202;
//blitting amoutn background box
SDL_Surface *amountBG = NULL;
if(stacks[stackAliveByHex[b][v]].effects.size() == 0)
if(curStack.effects.size() == 0)
{
amountBG = amountNormal;
}
else
{
int pos=0; //determining total positiveness of effects
for(int c=0; c<stacks[stackAliveByHex[b][v]].effects.size(); ++c)
for(int c=0; c<curStack.effects.size(); ++c)
{
pos += CGI->spellh->spells[ stacks[stackAliveByHex[b][v]].effects[c].id ].positiveness;
pos += CGI->spellh->spells[ curStack.effects[c].id ].positiveness;
}
if(pos > 0)
{
@ -542,14 +552,14 @@ void CBattleInterface::show(SDL_Surface * to)
amountBG = amountEffNeutral;
}
}
SDL_BlitSurface(amountBG, NULL, to, &genRect(amountNormal->h, amountNormal->w, creAnims[stackAliveByHex[b][v]]->pos.x + xAdd + pos.x, creAnims[stackAliveByHex[b][v]]->pos.y + 260 + pos.y));
SDL_BlitSurface(amountBG, NULL, to, &genRect(amountNormal->h, amountNormal->w, creAnims[curStackID]->pos.x + xAdd + pos.x, creAnims[curStackID]->pos.y + 260 + pos.y));
//blitting amount
std::stringstream ss;
ss<<stacks[stackAliveByHex[b][v]].amount;
ss<<curStack.amount;
CSDL_Ext::printAtMiddleWB(
ss.str(),
creAnims[stackAliveByHex[b][v]]->pos.x + xAdd + 14 + pos.x,
creAnims[stackAliveByHex[b][v]]->pos.y + 260 + 4 + pos.y,
creAnims[curStackID]->pos.x + xAdd + 14 + pos.x,
creAnims[curStackID]->pos.y + 260 + 4 + pos.y,
GEOR13,
20,
zwykly,

View File

@ -698,4 +698,9 @@ CPath * CCallback::getPath( int3 src, int3 dest, const CGHeroInstance * hero )
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->getPath(src,dest,hero);
}
void CCallback::save( const std::string &fname )
{
cl->save(fname);
}

View File

@ -47,6 +47,7 @@ public:
virtual void setFormation(const CGHeroInstance * hero, bool tight)=0;
virtual void setSelection(const CArmedInstance * obj)=0;
virtual void recruitHero(const CGTownInstance *town, const CGHeroInstance *hero)=0;
virtual void save(const std::string &fname) = 0;
//get info
virtual bool verifyPath(CPath * path, bool blockSea)const =0;
@ -136,6 +137,7 @@ public:
void setFormation(const CGHeroInstance * hero, bool tight);
void setSelection(const CArmedInstance * obj);
void recruitHero(const CGTownInstance *town, const CGHeroInstance *hero);
void save(const std::string &fname);
//get info
bool verifyPath(CPath * path, bool blockSea) const;

View File

@ -62,7 +62,7 @@ public:
virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town){};
virtual void init(ICallback * CB){};
virtual void receivedResource(int type, int val){};
virtual void showInfoDialog(std::string &text, const std::vector<Component*> &components){};
virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components){};
virtual void showSelDialog(std::string &text, const std::vector<Component*> &components, ui32 askID){};
virtual void showYesNoDialog(std::string &text, const std::vector<Component*> &components, ui32 askID){};
virtual void tileHidden(const std::set<int3> &pos){};

View File

@ -1455,12 +1455,6 @@ int CGameState::canBuildStructure( const CGTownInstance *t, int ID )
{
int ret = 7; //allowed by default
//can we build it?
if(t->forbiddenBuildings.find(ID)!=t->forbiddenBuildings.end())
ret = 2; //forbidden
else if(t->builded >= MAX_BUILDING_PER_TURN)
ret = 5; //building limit
//checking resources
CBuilding * pom = VLC->buildh->buildings[t->subID][ID];
for(int res=0;res<7;res++) //TODO: support custom amount of resources
@ -1478,6 +1472,12 @@ int CGameState::canBuildStructure( const CGTownInstance *t, int ID )
ret = 8; //lack of requirements - cannot build
}
//can we build it?
if(t->forbiddenBuildings.find(ID)!=t->forbiddenBuildings.end())
ret = 2; //forbidden
else if(t->builded >= MAX_BUILDING_PER_TURN)
ret = 5; //building limit
if(ID == 13) //capitol
{
for(int in = 0; in < map->towns.size(); in++)
@ -1672,17 +1672,22 @@ bool CGameState::checkForVisitableDir(const int3 & src, const int3 & dst) const
int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting)
{
int attackerAttackBonus = attacker->creature->attack + (attackerHero ? attackerHero->getPrimSkillLevel(0) : 0);
int attackerAttackBonus = attacker->creature->attack + (attackerHero ? attackerHero->getPrimSkillLevel(0) : 0),
defenderDefenseBonus = defender->creature->defence + (defendingHero ? defendingHero->getPrimSkillLevel(1) : 0),
attackDefenseBonus = 0,
minDmg = attacker->creature->damageMin * attacker->amount,
maxDmg = attacker->creature->damageMax * attacker->amount;
//calculating total attack/defense skills modifier
if(attacker->getEffect(56)) //frenzy for attacker
{
attackerAttackBonus += (VLC->spellh->spells[attacker->getEffect(56)->id].powers[attacker->getEffect(56)->level]/100.0) *(attacker->creature->defence + (attackerHero ? attackerHero->getPrimSkillLevel(1) : 0));
}
int defenderDefenseBonus = defender->creature->defence + (defendingHero ? defendingHero->getPrimSkillLevel(1) : 0);
if(defender->getEffect(56)) //frenzy for defender
{
defenderDefenseBonus = 0;
}
int attackDefenseBonus = attackerAttackBonus - defenderDefenseBonus;
attackDefenseBonus = attackerAttackBonus - defenderDefenseBonus;
if(defender->getEffect(48)) //defender's prayer handling
{
attackDefenseBonus -= VLC->spellh->spells[defender->getEffect(48)->id].powers[defender->getEffect(48)->level];
@ -1703,27 +1708,10 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
{
attackDefenseBonus += VLC->spellh->spells[attacker->getEffect(43)->id].powers[attacker->getEffect(43)->level];
}
int damageBase = 0;
if(attacker->getEffect(42)) //curse handling (partial, the rest is below)
{
damageBase = attacker->creature->damageMin;
damageBase -= VLC->spellh->spells[attacker->getEffect(42)->id].powers[attacker->getEffect(42)->level];
}
else if(attacker->getEffect(41)) //bless handling
{
damageBase = attacker->creature->damageMax;
damageBase += VLC->spellh->spells[attacker->getEffect(41)->id].powers[attacker->getEffect(41)->level];
}
else if(attacker->creature->damageMax == attacker->creature->damageMin) //constant damage
{
damageBase = attacker->creature->damageMin;
}
else
{
damageBase = rand()%(attacker->creature->damageMax - attacker->creature->damageMin) + attacker->creature->damageMin + 1;
}
float dmgBonusMultiplier = 1.0f;
//bonus from attack/defense skills
if(attackDefenseBonus < 0) //decreasing dmg
{
if(0.02f * (-attackDefenseBonus) > 0.3f)
@ -1746,6 +1734,7 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
dmgBonusMultiplier += 0.05f * attackDefenseBonus;
}
}
//handling secondary abilities
if(attackerHero)
{
@ -1766,7 +1755,7 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
}
else
{
switch(attackerHero->getSecSkillLevel(22)) //offence
switch(attackerHero->getSecSkillLevel(22)) //offense
{
case 1: //basic
dmgBonusMultiplier *= 1.1f;
@ -1782,7 +1771,7 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
}
if(defendingHero)
{
switch(defendingHero->getSecSkillLevel(23)) //armourer
switch(defendingHero->getSecSkillLevel(23)) //armorer
{
case 1: //basic
dmgBonusMultiplier *= 0.95f;
@ -1803,20 +1792,44 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
else //adv or expert
dmgBonusMultiplier *= 0.7f;
}
if(shooting && defender->getEffect(28)) //air shield
else if(shooting && defender->getEffect(28)) //air shield
{
if(defender->getEffect(28)->level<=1) //none or basic
dmgBonusMultiplier *= 0.75f;
else //adv or expert
dmgBonusMultiplier *= 0.5f;
}
if(attacker->getEffect(42)) //curse, second part of handling
if(attacker->getEffect(42)) //curse handling (partial, the rest is below)
{
if(attacker->getEffect(42)->level>=2) //adv or expert
dmgBonusMultiplier *= 0.8f;
}
return int( (float)damageBase * (float)attacker->amount * dmgBonusMultiplier );
minDmg *= dmgBonusMultiplier;
maxDmg *= dmgBonusMultiplier;
if(attacker->getEffect(42)) //curse handling (rest)
{
minDmg -= VLC->spellh->spells[attacker->getEffect(42)->id].powers[attacker->getEffect(42)->level];
return minDmg;
}
else if(attacker->getEffect(41)) //bless handling
{
maxDmg += VLC->spellh->spells[attacker->getEffect(41)->id].powers[attacker->getEffect(41)->level];
return maxDmg;
}
else
{
if(minDmg != maxDmg)
return minDmg + rand() % (maxDmg - minDmg + 1);
else
return minDmg;
}
tlog1 << "We are too far in calculateDmg...\n";
return -1;
}
void BattleInfo::calculateCasualties( std::set<std::pair<ui32,si32> > *casualties )

View File

@ -279,7 +279,7 @@ SDL_Surface * CMessage::drawBoxTextBitmapSub( int player, std::string text, SDL_
curh += imgToBmp;
blitAt(bitmap,(ret->w/2)-(bitmap->w/2),curh,ret);
curh += bitmap->h + 5;
CSDL_Ext::printAtMiddle(sub,ret->w/2,curh+( ((*txtg)[0][0]->h) / 2 ),GEOR13,zwykly,ret);
CSDL_Ext::printAtMiddle(sub,ret->w/2,curh+10,GEOR13,zwykly,ret);
delete tekst;
delete txtg;
return ret;

View File

@ -33,6 +33,7 @@
#include <boost/algorithm/string/replace.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread.hpp>
#include <cmath>
#include <queue>
@ -1081,6 +1082,7 @@ void TimeInterested::deactivate()
CPlayerInterface::CPlayerInterface(int Player, int serial)
{
LOCPLINT = this;
curAction = NULL;
curint = NULL;
playerID=Player;
serialID=serial;
@ -2374,7 +2376,7 @@ void CPlayerInterface::showComp(SComponent comp)
adventureInt->infoBar.showComp(&comp,4000);
}
void CPlayerInterface::showInfoDialog(std::string &text, const std::vector<Component*> &components)
void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<Component*> &components)
{
std::vector<SComponent*> intComps;
for(int i=0;i<components.size();i++)
@ -2382,7 +2384,7 @@ void CPlayerInterface::showInfoDialog(std::string &text, const std::vector<Compo
showInfoDialog(text,intComps);
}
void CPlayerInterface::showInfoDialog(std::string &text, const std::vector<SComponent*> & components)
void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<SComponent*> & components, bool deactivateCur)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
@ -2392,9 +2394,12 @@ void CPlayerInterface::showInfoDialog(std::string &text, const std::vector<SComp
if(makingTurn && curint)
{
temp->buttons[0]->callback += boost::bind(&IActivable::activate,LOCPLINT->curint);
showingDialog->set(true);
curint->deactivate(); //dezaktywacja starego interfejsu
if(deactivateCur)
{
temp->buttons[0]->callback += boost::bind(&IActivable::activate,LOCPLINT->curint);
curint->deactivate(); //dezaktywacja starego interfejsu
}
temp->activate();
LOCPLINT->objsToBlit.push_back(temp);
}
@ -4249,6 +4254,8 @@ CSystemOptionsWindow::CSystemOptionsWindow(const SDL_Rect &pos, CPlayerInterface
CSDL_Ext::printAt(CGI->generaltexth->allTexts[577], 283, 217, GEOR16, zwykly, background); //spell book animation
//setting up buttons
save = new AdventureMapButton (CGI->generaltexth->zelp[321].first, CGI->generaltexth->zelp[321].second, boost::bind(&CSystemOptionsWindow::bsavef, this), 516, 354, "SOSAVE.DEF", SDLK_s);
std::swap(save->imgs[0][0], save->imgs[0][1]);
quitGame = new AdventureMapButton (CGI->generaltexth->zelp[324].first, CGI->generaltexth->zelp[324].second, boost::bind(&CSystemOptionsWindow::bquitf, this), 405, 471, "soquit.def", SDLK_q);
std::swap(quitGame->imgs[0][0], quitGame->imgs[0][1]);
backToMap = new AdventureMapButton (CGI->generaltexth->zelp[325].first, CGI->generaltexth->zelp[325].second, boost::bind(&CSystemOptionsWindow::breturnf, this), 516, 471, "soretrn.def", SDLK_RETURN);
@ -4274,6 +4281,7 @@ CSystemOptionsWindow::~CSystemOptionsWindow()
{
SDL_FreeSurface(background);
delete save;
delete quitGame;
delete backToMap;
delete heroMoveSpeed;
@ -4303,8 +4311,21 @@ void CSystemOptionsWindow::breturnf()
LOCPLINT->curint->activate();
}
void CSystemOptionsWindow::bsavef()
{
using namespace boost::posix_time;
std::ostringstream fnameStream;
fnameStream << second_clock::local_time();
std::string fname = fnameStream.str();
boost::algorithm::replace_all(fname,":","");
boost::algorithm::replace_all(fname," ","-");
LOCPLINT->showYesNoDialog("Do you want to save current game as " + fname, std::vector<SComponent*>(), boost::bind(&CCallback::save, LOCPLINT->cb, fname), boost::bind(&CSystemOptionsWindow::activate, this), false, false);
}
void CSystemOptionsWindow::activate()
{
save->activate();
quitGame->activate();
backToMap->activate();
heroMoveSpeed->activate();
@ -4313,6 +4334,7 @@ void CSystemOptionsWindow::activate()
void CSystemOptionsWindow::deactivate()
{
save->deactivate();
quitGame->deactivate();
backToMap->deactivate();
heroMoveSpeed->deactivate();
@ -4327,6 +4349,7 @@ void CSystemOptionsWindow::show(SDL_Surface *to)
SDL_BlitSurface(background, NULL, to, &pos);
save->show(to);
quitGame->show(to);
backToMap->show(to);
heroMoveSpeed->show(to);

View File

@ -538,7 +538,7 @@ public:
void heroMovePointsChanged(const CGHeroInstance * hero);
void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town);
void receivedResource(int type, int val);
void showInfoDialog(std::string &text, const std::vector<Component*> &components);
void showInfoDialog(const std::string &text, const std::vector<Component*> &components);
void showSelDialog(std::string &text, const std::vector<Component*> &components, ui32 askID);
void showYesNoDialog(std::string &text, const std::vector<Component*> &components, ui32 askID);
void tileHidden(const std::set<int3> &pos);
@ -577,7 +577,7 @@ public:
void init(ICallback * CB);
int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
void removeObjToBlit(IShowable* obj);
void showInfoDialog(std::string &text, const std::vector<SComponent*> & components);
void showInfoDialog(const std::string &text, const std::vector<SComponent*> & components, bool deactivateCur=true);
void showYesNoDialog(std::string &text, const std::vector<SComponent*> & components, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool deactivateCur, bool DelComps); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close
bool moveHero(const CGHeroInstance *h, CPath * path);
@ -838,14 +838,15 @@ class CSystemOptionsWindow : public IShowActivable, public CIntObject
{
private:
SDL_Surface * background; //background of window
AdventureMapButton * quitGame, * backToMap;
AdventureMapButton *load, *save, *restart, *mainMenu, * quitGame, * backToMap; //load, restart and main menu are not used yet
CHighlightableButtonsGroup * heroMoveSpeed;
CHighlightableButtonsGroup * mapScrollSpeed;
public:
CSystemOptionsWindow(const SDL_Rect & pos, CPlayerInterface * owner); //c-tor
~CSystemOptionsWindow(); //d-tor
//functions for butons
//functions bound to buttons
void bsavef(); //save game
void bquitf(); //quit game
void breturnf(); //return to game

View File

@ -973,7 +973,8 @@ void MapSel::printMaps(int from, int to, int at, bool abs)
}
else
{
CSDL_Ext::printAtMiddle(curVector()[(i-at)+from]->filename,192,13,GEOR13,nasz,scenin, 2);
std::string &name = curVector()[(i-at)+from]->filename;
CSDL_Ext::printAtMiddle(name.substr(6,name.size()-12),192,13,GEOR13,nasz,scenin, 2);
}
if (curVector()[(i-at)+from]->victoryCondition.condition == winStandard)
temp=11;
@ -1064,6 +1065,7 @@ void MapSel::show()
//print scenario list
printMaps(0,18);
slid->whereAreWe = 0;
slid->activate();
//SDL_Flip(screen);

View File

@ -458,7 +458,15 @@ void CCreatureHandler::loadCreatures()
creatures[140].abilities.insert(DOUBLE_WIDE);//boar should be treated as double-wide
creatures[142].abilities.insert(DOUBLE_WIDE);//nomads should be treated as double-wide
creatures[46].abilities -= FLYING;
creatures[46].abilities -= FLYING; //hell hound
creatures[47].abilities -= FLYING; //cerberus
creatures[52].abilities += FLYING; //Efreeti
creatures[53].abilities += FLYING; //Efreet Sultan
creatures[47].abilities += MULTI_HEAD_ATTACK; //cerberus
creatures[88].abilities += TWICE_ATTACK; //wolf raider
}
void CCreatureHandler::loadAnimationInfo()

View File

@ -709,7 +709,7 @@ std::vector<std::pair<int,std::string> > CGHeroInstance::getCurrentMoraleModifie
{
char buf[100];
sprintf(buf,VLC->generaltexth->arraytxt[117].c_str(),VLC->creh->creatures[13].namePl.c_str());
ret.push_back(std::pair<int,std::string>(-1,buf)); //%s in group +1
ret.push_back(std::pair<int,std::string>(1,buf)); //%s in group +1
}
}

View File

@ -824,7 +824,7 @@ struct EndTurn : public CPackForServer
struct DismissHero : public CPackForServer
{
DismissHero(){};
DismissHero(si32 HID) : hid(hid) {};
DismissHero(si32 HID) : hid(HID) {};
si32 hid;
void applyGh(CGameHandler *gh);

View File

@ -481,6 +481,7 @@ void CGameHandler::prepareAttacked(BattleStackAttacked &bsa, CStack *def)
void CGameHandler::prepareAttack(BattleAttack &bat, CStack *att, CStack *def)
{
bat.bsa.clear();
bat.stackAttacking = att->ID;
std::set<BattleStackAttacked>::iterator i = bat.bsa.insert(BattleStackAttacked()).first;
BattleStackAttacked *bsa = (BattleStackAttacked *) &*i;