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