1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-15 00:05:02 +02:00

* compiles under MSVC (haven't I broken anything on gcc?)

* half-done support for battles
This commit is contained in:
Michał W. Urbańczyk
2008-08-04 15:56:36 +00:00
parent 038dd90517
commit a15ffb06e6
28 changed files with 899 additions and 308 deletions

View File

@ -17,14 +17,36 @@
#include "../hch/CHeroHandler.h"
#include "boost/date_time/posix_time/posix_time_types.hpp" //no i/o just types
#include "../lib/VCMI_Lib.h"
#include <boost/thread.hpp>
#include "../lib/CondSh.h"
#include <boost/thread/xtime.hpp>
extern bool end2;
bool makingTurn;
#include "../lib/BattleAction.h"
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
#define NEW_ROUND BattleNextRound bnr;\
bnr.round = gs->curB->round + 1;\
sendAndApply(&bnr);
boost::condition_variable cTurn;
boost::mutex mTurn;
boost::shared_mutex gsm;
CondSh<bool> battleMadeAction;
CondSh<BattleResult *> battleResult(NULL);
class CMP_stack
{
public:
bool operator ()(const CStack* a, const CStack* b)
{
return (a->creature->speed)>(b->creature->speed);
}
} cmpst ;
double distance(int3 a, int3 b)
{
return std::sqrt( (double)(a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
@ -51,6 +73,268 @@ void CGameHandler::handleCPPObjS(std::map<int,CCPPObjectScript*> * mapa, CCPPObj
cppscripts.insert(script);
}
void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
{
SetPrimSkill sps;
sps.id = ID;
sps.which = which;
sps.abs = abs;
sps.val = val;
sendAndApply(&sps);
if(which==4)
{
CGHeroInstance *hero = static_cast<CGHeroInstance *>(gs->map->objects[ID]);
if(hero->exp >= VLC->heroh->reqExp(hero->level+1)) //new level
{
//hero->level++;
//give prim skill
std::cout << hero->name <<" got level "<<hero->level<<std::endl;
int r = rand()%100, pom=0, x=0;
int std::pair<int,int>::*g = (hero->level>9) ? (&std::pair<int,int>::second) : (&std::pair<int,int>::first);
for(;x<PRIMARY_SKILLS;x++)
{
pom += hero->type->heroClass->primChance[x].*g;
if(r<pom)
break;
}
std::cout << "Bohater dostaje umiejetnosc pierwszorzedna " << x << " (wynik losowania "<<r<<")"<<std::endl;
SetPrimSkill sps;
sps.id = ID;
sps.which = x;
sps.abs = false;
sps.val = 1;
sendAndApply(&sps);
hero->primSkills[x]++;
std::set<ui16> choice;
std::set<int> basicAndAdv, expert, none;
for(int i=0;i<SKILL_QUANTITY;i++) none.insert(i);
for(unsigned i=0;i<hero->secSkills.size();i++)
{
if(hero->secSkills[i].second < 2)
basicAndAdv.insert(hero->secSkills[i].first);
else
expert.insert(hero->secSkills[i].first);
none.erase(hero->secSkills[i].first);
}
if(hero->secSkills.size() < hero->type->heroClass->skillLimit) //free skill slot
{
choice.insert(hero->type->heroClass->chooseSecSkill(none)); //new skill
}
else
{
int s = hero->type->heroClass->chooseSecSkill(basicAndAdv);
choice.insert(s);
basicAndAdv.erase(s);
}
if(basicAndAdv.size())
{
choice.insert(hero->type->heroClass->chooseSecSkill(basicAndAdv)); //new skill
}
else if(hero->secSkills.size() < hero->type->heroClass->skillLimit)
{
choice.insert(hero->type->heroClass->chooseSecSkill(none)); //new skill
}
}
//TODO - powiadomic interfejsy, sprawdzic czy nie ma awansu itp
}
}
void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2)
{
BattleInfo *curB = new BattleInfo;
//battle start
{
battleResult.set(NULL);
std::vector<CStack*> & stacks = (curB->stacks);
curB->army1=army1;
curB->army2=army2;
curB->hero1=(hero1)?(hero1->id):(-1);
curB->hero2=(hero1)?(hero1->id):(-1);
curB->side1=(hero1)?(hero1->tempOwner):(-1);
curB->side2=(hero2)?(hero2->tempOwner):(-1);
curB->round = -2;
curB->activeStack = -1;
for(std::map<si32,std::pair<ui32,si32> >::iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
{
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true));
stacks[stacks.size()-1]->ID = stacks.size()-1;
}
//initialization of positions
switch(army1.slots.size()) //for attacker
{
case 0:
break;
case 1:
stacks[0]->position = 86; //6
break;
case 2:
stacks[0]->position = 35; //3
stacks[1]->position = 137; //9
break;
case 3:
stacks[0]->position = 35; //3
stacks[1]->position = 86; //6
stacks[2]->position = 137; //9
break;
case 4:
stacks[0]->position = 1; //1
stacks[1]->position = 69; //5
stacks[2]->position = 103; //7
stacks[3]->position = 171; //11
break;
case 5:
stacks[0]->position = 1; //1
stacks[1]->position = 35; //3
stacks[2]->position = 86; //6
stacks[3]->position = 137; //9
stacks[4]->position = 171; //11
break;
case 6:
stacks[0]->position = 1; //1
stacks[1]->position = 35; //3
stacks[2]->position = 69; //5
stacks[3]->position = 103; //7
stacks[4]->position = 137; //9
stacks[5]->position = 171; //11
break;
case 7:
stacks[0]->position = 1; //1
stacks[1]->position = 35; //3
stacks[2]->position = 69; //5
stacks[3]->position = 86; //6
stacks[4]->position = 103; //7
stacks[5]->position = 137; //9
stacks[6]->position = 171; //11
break;
default: //fault
break;
}
for(std::map<si32,std::pair<ui32,si32> >::iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero2 ? hero2->tempOwner : 255, stacks.size(), false));
switch(army2.slots.size()) //for defender
{
case 0:
break;
case 1:
stacks[0+army1.slots.size()]->position = 100; //6
break;
case 2:
stacks[0+army1.slots.size()]->position = 49; //3
stacks[1+army1.slots.size()]->position = 151; //9
break;
case 3:
stacks[0+army1.slots.size()]->position = 49; //3
stacks[1+army1.slots.size()]->position = 100; //6
stacks[2+army1.slots.size()]->position = 151; //9
break;
case 4:
stacks[0+army1.slots.size()]->position = 15; //1
stacks[1+army1.slots.size()]->position = 83; //5
stacks[2+army1.slots.size()]->position = 117; //7
stacks[3+army1.slots.size()]->position = 185; //11
break;
case 5:
stacks[0+army1.slots.size()]->position = 15; //1
stacks[1+army1.slots.size()]->position = 49; //3
stacks[2+army1.slots.size()]->position = 100; //6
stacks[3+army1.slots.size()]->position = 151; //9
stacks[4+army1.slots.size()]->position = 185; //11
break;
case 6:
stacks[0+army1.slots.size()]->position = 15; //1
stacks[1+army1.slots.size()]->position = 49; //3
stacks[2+army1.slots.size()]->position = 83; //5
stacks[3+army1.slots.size()]->position = 117; //7
stacks[4+army1.slots.size()]->position = 151; //9
stacks[5+army1.slots.size()]->position = 185; //11
break;
case 7:
stacks[0+army1.slots.size()]->position = 15; //1
stacks[1+army1.slots.size()]->position = 49; //3
stacks[2+army1.slots.size()]->position = 83; //5
stacks[3+army1.slots.size()]->position = 100; //6
stacks[4+army1.slots.size()]->position = 117; //7
stacks[5+army1.slots.size()]->position = 151; //9
stacks[6+army1.slots.size()]->position = 185; //11
break;
default: //fault
break;
}
for(unsigned g=0; g<stacks.size(); ++g) //shifting positions of two-hex creatures
{
if((stacks[g]->position%17)==1 && stacks[g]->creature->isDoubleWide())
{
stacks[g]->position += 1;
}
else if((stacks[g]->position%17)==15 && stacks[g]->creature->isDoubleWide())
{
stacks[g]->position -= 1;
}
}
std::stable_sort(stacks.begin(),stacks.end(),cmpst);
//block engaged players
if(hero1->tempOwner<PLAYER_LIMIT)
states[hero1->tempOwner] += 10;
if(hero2 && hero2->tempOwner<PLAYER_LIMIT)
states[hero2->tempOwner] += 10;
//send info about battles
BattleStart bs;
bs.info = curB;
sendAndApply(&bs);
NEW_ROUND;
}
//tactic round
{
NEW_ROUND;
if( (hero1 && hero1->getSecSkillLevel(19)>=0) ||
( hero2 && hero2->getSecSkillLevel(19)>=0) )//someone has tactics
{
//TODO: tactic round (round -1)
}
}
//main loop
while(!battleResult.get()) //till the end of the battle ;]
{
NEW_ROUND;
std::vector<CStack*> & stacks = (gs->curB->stacks);
const BattleInfo & curB = *gs->curB;
//stack loop
for(unsigned i=0;i<stacks.size() && !battleResult.get();i++)
{
if(!stacks[i]->alive) continue;//indicates imposiibility of making action for this dead unit
BattleSetActiveStack sas;
sas.stack = i;
sendAndApply(&sas);
//wait for response about battle action
boost::unique_lock<boost::mutex> lock(battleMadeAction.mx);
while(!battleMadeAction.data)
battleMadeAction.cond.wait(lock);
}
}
//end battle, remove all info, free memory
sendAndApply(battleResult.data);
delete battleResult.data;
//for(int i=0;i<stacks.size();i++)
// delete stacks[i];
//delete curB;
//curB = NULL;
}
void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
{
try
@ -65,7 +349,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
case 100: //my interface ended its turn
{
mTurn.lock();
makingTurn = false;
states[gs->currentPlayer] = 0;
mTurn.unlock();
cTurn.notify_all();
break;
@ -290,6 +574,47 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
sr.res[i]-=b->resources[i];
sendAndApply(&sr);
break;
}
case 3002:
{
BattleAction ba;
c >> ba;
switch(ba.actionType)
{
case 2: //walk
{
//battleMoveCreatureStack(ba.stackNumber, ba.destinationTile);
break;
}
case 3: //defend
{
break;
}
case 4: //retreat/flee
{
//TODO: check if fleeing is possible (e.g. enemy may have Shackles of War)
//TODO: calculate casualties
//TODO: remove retreating hero from map and place it in recrutation list
BattleResult *br = new BattleResult;
br->result = 1;
battleResult.set(br);
break;
}
case 6: //walk or attack
{
//battleMoveCreatureStack(ba.stackNumber, ba.destinationTile);
//battleAttackCreatureStack(ba.stackNumber, ba.destinationTile);
break;
}
case 7: //shoot
{
//battleShootCreatureStack(ba.stackNumber, ba.destinationTile);
break;
}
}
battleMadeAction.setn(true);
//sprawdzic czy po tej akcji ktoras strona nie wygrala bitwy
break;
}
default:
@ -490,12 +815,12 @@ void CGameHandler::run()
for(std::map<ui8,PlayerState>::iterator i = gs->players.begin(); i != gs->players.end(); i++)
{
if((i->second.towns.size()==0 && i->second.heroes.size()==0) || i->second.color<0 || i->first>=PLAYER_LIMIT ) continue; //players has not towns/castle - loser
makingTurn = true;
states[i->first] = 1;
gs->currentPlayer = i->first;
*connections[i->first] << ui16(100) << i->first;
//wait till turn is done
boost::unique_lock<boost::mutex> lock(mTurn);
while(makingTurn && !end2)
while(states[i->first] && !end2)
{
boost::posix_time::time_duration p;
p= boost::posix_time::seconds(1);
@ -503,7 +828,6 @@ void CGameHandler::run()
time.sec = static_cast<boost::xtime::xtime_sec_t>(p.total_seconds());
cTurn.timed_wait(lock,time);
}
}
}
}