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

* minor campaign related improvements

This commit is contained in:
mateuszb 2012-09-22 15:16:45 +00:00
parent 8f936cd34d
commit 82e21f8b6e
5 changed files with 112 additions and 97 deletions

View File

@ -2871,12 +2871,7 @@ CBonusSelection::CBonusSelection(shared_ptr<CCampaignState> _ourCampaign)
CBonusSelection::CBonusSelection( std::string campaignFName ) CBonusSelection::CBonusSelection( std::string campaignFName )
{ {
ourCampaign = make_shared<CCampaignState>(); ourCampaign = make_shared<CCampaignState>(CCampaignHandler::getCampaign(campaignFName));
ourCampaign->camp = CCampaignHandler::getCampaign(campaignFName);
for(int i = 0; i < ourCampaign->camp->scenarios.size(); i++)
{
ourCampaign->mapsRemaining.push_back(i);
}
sInfo.campState = ourCampaign; sInfo.campState = ourCampaign;
init(); init();

View File

@ -708,7 +708,7 @@ CConnection * CServerHandler::connectToServer()
if(!shared->sr->ready) if(!shared->sr->ready)
waitForServer(); waitForServer();
th.update(); th.update(); //put breakpoint here to attach to server before it does something stupid
CConnection *ret = justConnectToServer(settings["server"]["server"].String(), port); CConnection *ret = justConnectToServer(settings["server"]["server"].String(), port);
if(verbose) if(verbose)

View File

@ -179,50 +179,50 @@ CScenarioTravel CCampaignHandler::readScenarioTravelFromMemory( const ui8 * buff
//hero: FFFD means 'most powerful' and FFFE means 'generated' //hero: FFFD means 'most powerful' and FFFE means 'generated'
switch(bonus.type) switch(bonus.type)
{ {
case 0: //spell case CScenarioTravel::STravelBonus::SPELL:
{ {
bonus.info1 = read_le_u16(buffer + outIt); outIt += 2; //hero bonus.info1 = read_le_u16(buffer + outIt); outIt += 2; //hero
bonus.info2 = buffer[outIt++]; //spell ID bonus.info2 = buffer[outIt++]; //spell ID
break; break;
} }
case 1: //monster case CScenarioTravel::STravelBonus::MONSTER:
{ {
bonus.info1 = read_le_u16(buffer + outIt); outIt += 2; //hero bonus.info1 = read_le_u16(buffer + outIt); outIt += 2; //hero
bonus.info2 = read_le_u16(buffer + outIt); outIt += 2; //monster type bonus.info2 = read_le_u16(buffer + outIt); outIt += 2; //monster type
bonus.info3 = read_le_u16(buffer + outIt); outIt += 2; //monster count bonus.info3 = read_le_u16(buffer + outIt); outIt += 2; //monster count
break; break;
} }
case 2: //building case CScenarioTravel::STravelBonus::BUILDING:
{ {
bonus.info1 = buffer[outIt++]; //building ID (0 - town hall, 1 - city hall, 2 - capitol, etc) bonus.info1 = buffer[outIt++]; //building ID (0 - town hall, 1 - city hall, 2 - capitol, etc)
break; break;
} }
case 3: //artifact case CScenarioTravel::STravelBonus::ARTIFACT:
{ {
bonus.info1 = read_le_u16(buffer + outIt); outIt += 2; //hero bonus.info1 = read_le_u16(buffer + outIt); outIt += 2; //hero
bonus.info2 = read_le_u16(buffer + outIt); outIt += 2; //artifact ID bonus.info2 = read_le_u16(buffer + outIt); outIt += 2; //artifact ID
break; break;
} }
case 4: //spell scroll case CScenarioTravel::STravelBonus::SPELL_SCROLL:
{ {
bonus.info1 = read_le_u16(buffer + outIt); outIt += 2; //hero bonus.info1 = read_le_u16(buffer + outIt); outIt += 2; //hero
bonus.info2 = buffer[outIt++]; //spell ID bonus.info2 = buffer[outIt++]; //spell ID
break; break;
} }
case 5: //prim skill case CScenarioTravel::STravelBonus::PRIMARY_SKILL:
{ {
bonus.info1 = read_le_u16(buffer + outIt); outIt += 2; //hero bonus.info1 = read_le_u16(buffer + outIt); outIt += 2; //hero
bonus.info2 = read_le_u32(buffer + outIt); outIt += 4; //bonuses (4 bytes for 4 skills) bonus.info2 = read_le_u32(buffer + outIt); outIt += 4; //bonuses (4 bytes for 4 skills)
break; break;
} }
case 6: //sec skills case CScenarioTravel::STravelBonus::SECONDARY_SKILL:
{ {
bonus.info1 = read_le_u16(buffer + outIt); outIt += 2; //hero bonus.info1 = read_le_u16(buffer + outIt); outIt += 2; //hero
bonus.info2 = buffer[outIt++]; //skill ID bonus.info2 = buffer[outIt++]; //skill ID
bonus.info3 = buffer[outIt++]; //skill level bonus.info3 = buffer[outIt++]; //skill level
break; break;
} }
case 7: //resources case CScenarioTravel::STravelBonus::RESOURCE:
{ {
bonus.info1 = buffer[outIt++]; //type bonus.info1 = buffer[outIt++]; //type
//FD - wood+ore //FD - wood+ore
@ -241,7 +241,7 @@ CScenarioTravel CCampaignHandler::readScenarioTravelFromMemory( const ui8 * buff
for (int g=0; g<numOfBonuses; ++g) for (int g=0; g<numOfBonuses; ++g)
{ {
CScenarioTravel::STravelBonus bonus; CScenarioTravel::STravelBonus bonus;
bonus.type = 8; bonus.type = CScenarioTravel::STravelBonus::PLAYER_PREV_SCENARIO;
bonus.info1 = buffer[outIt++]; //player color bonus.info1 = buffer[outIt++]; //player color
bonus.info2 = buffer[outIt++]; //from what scenario bonus.info2 = buffer[outIt++]; //from what scenario
@ -255,7 +255,7 @@ CScenarioTravel CCampaignHandler::readScenarioTravelFromMemory( const ui8 * buff
for (int g=0; g<numOfBonuses; ++g) for (int g=0; g<numOfBonuses; ++g)
{ {
CScenarioTravel::STravelBonus bonus; CScenarioTravel::STravelBonus bonus;
bonus.type = 9; bonus.type = CScenarioTravel::STravelBonus::HERO;
bonus.info1 = buffer[outIt++]; //player color bonus.info1 = buffer[outIt++]; //player color
bonus.info2 = read_le_u16(buffer + outIt); outIt += 2; //hero, FF FF - random bonus.info2 = read_le_u16(buffer + outIt); outIt += 2; //hero, FF FF - random
@ -409,7 +409,8 @@ void CCampaignScenario::prepareCrossoverHeroes( std::vector<CGHeroInstance *> he
bool CScenarioTravel::STravelBonus::isBonusForHero() const bool CScenarioTravel::STravelBonus::isBonusForHero() const
{ {
return type == 0 || type == 1 || type == 3 || type == 4 || type == 5 || type == 6; return type == SPELL || type == MONSTER || type == ARTIFACT || type == SPELL_SCROLL || type == PRIMARY_SKILL
|| type == SECONDARY_SKILL;
} }
// void CCampaignState::initNewCampaign( const StartInfo &si ) // void CCampaignState::initNewCampaign( const StartInfo &si )
@ -446,3 +447,14 @@ ui8 CCampaignState::currentBonusID() const
{ {
return chosenCampaignBonuses[currentMap]; return chosenCampaignBonuses[currentMap];
} }
CCampaignState::CCampaignState()
{}
CCampaignState::CCampaignState( unique_ptr<CCampaign> _camp ) : camp(std::move(_camp))
{
for(int i = 0; i < camp->scenarios.size(); i++)
{
mapsRemaining.push_back(i);
}
}

View File

@ -55,8 +55,9 @@ public:
struct DLL_LINKAGE STravelBonus struct DLL_LINKAGE STravelBonus
{ {
ui8 type; //0 - spell, 1 - monster, 2 - building, 3 - artifact, 4 - spell scroll, 5 - prim skill, 6 - sec skill, 7 - resource, enum EBonusType {SPELL, MONSTER, BUILDING, ARTIFACT, SPELL_SCROLL, PRIMARY_SKILL, SECONDARY_SKILL, RESOURCE,
//8 - player from previous scenario, 9 - hero [???] PLAYER_PREV_SCENARIO, HERO /*???*/};
ui8 type; //uses EBonusType
si32 info1, info2, info3; //purpose depends on type si32 info1, info2, info3; //purpose depends on type
bool isBonusForHero() const; bool isBonusForHero() const;
@ -152,6 +153,8 @@ public:
const CCampaignScenario &getCurrentScenario() const; const CCampaignScenario &getCurrentScenario() const;
ui8 currentBonusID() const; ui8 currentBonusID() const;
CCampaignState();
CCampaignState(unique_ptr<CCampaign> _camp);
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {

View File

@ -748,88 +748,78 @@ BattleInfo * CGameState::setupBattle(int3 tile, const CArmedInstance *armies[2],
void CGameState::init(StartInfo * si) void CGameState::init(StartInfo * si)
{ {
struct HLP auto giveCampaignBonusToHero = [&](CGHeroInstance * hero)
{ {
//it's assumed that given hero should receive the bonus const CScenarioTravel::STravelBonus & curBonus = scenarioOps->campState->getBonusForCurrentMap();
static void giveCampaignBonusToHero(CGHeroInstance * hero, const StartInfo * si, const CScenarioTravel & st, CGameState *gs ) if(curBonus.isBonusForHero())
{ {
const CScenarioTravel::STravelBonus & curBonus = si->campState->getBonusForCurrentMap(); //apply bonus
if(curBonus.isBonusForHero()) switch (curBonus.type)
{ {
//apply bonus case CScenarioTravel::STravelBonus::SPELL:
switch (curBonus.type) hero->spells.insert(curBonus.info2);
break;
case CScenarioTravel::STravelBonus::MONSTER:
{ {
case 0: //spell for(int i=0; i<GameConstants::ARMY_SIZE; i++)
hero->spells.insert(curBonus.info2);
break;
case 1: //monster
{ {
for(int i=0; i<GameConstants::ARMY_SIZE; i++) if(hero->slotEmpty(i))
{ {
if(hero->slotEmpty(i)) hero->addToSlot(i, curBonus.info2, curBonus.info3);
{ break;
hero->addToSlot(i, curBonus.info2, curBonus.info3);
break;
}
} }
} }
break;
case 3: //artifact
gs->giveHeroArtifact(hero, curBonus.info2);
break;
case 4: //spell scroll
{
CArtifactInstance * scroll = CArtifactInstance::createScroll(VLC->spellh->spells[curBonus.info2]);
scroll->putAt(ArtifactLocation(hero, scroll->firstAvailableSlot(hero)));
}
break;
case 5: //prim skill
{
const ui8* ptr = reinterpret_cast<const ui8*>(&curBonus.info2);
for (int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
{
int val = ptr[g];
if (val == 0)
{
continue;
}
Bonus *bb = new Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::CAMPAIGN_BONUS, val, si->campState->currentMap, g);
hero->addNewBonus(bb);
}
}
break;
case 6: //sec skills
hero->setSecSkillLevel(static_cast<CGHeroInstance::SecondarySkill>(curBonus.info2), curBonus.info3, true);
break;
} }
break;
case CScenarioTravel::STravelBonus::ARTIFACT:
gs->giveHeroArtifact(hero, curBonus.info2);
break;
case CScenarioTravel::STravelBonus::SPELL_SCROLL:
{
CArtifactInstance * scroll = CArtifactInstance::createScroll(VLC->spellh->spells[curBonus.info2]);
scroll->putAt(ArtifactLocation(hero, scroll->firstAvailableSlot(hero)));
}
break;
case CScenarioTravel::STravelBonus::PRIMARY_SKILL:
{
const ui8* ptr = reinterpret_cast<const ui8*>(&curBonus.info2);
for (int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
{
int val = ptr[g];
if (val == 0)
{
continue;
}
Bonus *bb = new Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::CAMPAIGN_BONUS, val, scenarioOps->campState->currentMap, g);
hero->addNewBonus(bb);
}
}
break;
case CScenarioTravel::STravelBonus::SECONDARY_SKILL:
hero->setSecSkillLevel(static_cast<CGHeroInstance::SecondarySkill>(curBonus.info2), curBonus.info3, true);
break;
} }
} }
};
static std::vector<const PlayerSettings *> getHumanPlayerInfo(const StartInfo * si) auto getHumanPlayerInfo = [&]() -> std::vector<const PlayerSettings *>
{
std::vector<const PlayerSettings *> ret;
for(auto it = scenarioOps->playerInfos.cbegin();
it != scenarioOps->playerInfos.cend(); ++it)
{ {
std::vector<const PlayerSettings *> ret; if(it->second.human)
for(std::map<int, PlayerSettings>::const_iterator it = si->playerInfos.begin(); ret.push_back(&it->second);
it != si->playerInfos.end(); ++it)
{
if(it->second.human)
ret.push_back(&it->second);
}
return ret;
} }
static void replaceHero( CGameState * gs, int objId, CGHeroInstance * ghi ) return ret;
{ };
ghi->id = objId;
gs->map->objects[objId] = ghi;
gs->map->heroes.push_back(ghi);
}
//sort in descending order by power auto replaceHero = [&](int objId, CGHeroInstance * ghi)
static bool heroPowerSorter(const CGHeroInstance * a, const CGHeroInstance * b) {
{ ghi->id = objId;
return a->getHeroStrength() > b->getHeroStrength(); gs->map->objects[objId] = ghi;
} gs->map->heroes.push_back(ghi);
}; };
tlog0 << "\tUsing random seed: "<< si->seedToBeUsed << std::endl; tlog0 << "\tUsing random seed: "<< si->seedToBeUsed << std::endl;
@ -881,6 +871,8 @@ void CGameState::init(StartInfo * si)
day = 0; day = 0;
loadTownDInfos(); loadTownDInfos();
tlog4 << "Initialization:";
tlog4 << "\tPicking grail position";
//pick grail location //pick grail location
if(map->grailPos.x < 0 || map->grailRadious) //grail not set or set within a radius around some place if(map->grailPos.x < 0 || map->grailRadious) //grail not set or set within a radius around some place
{ {
@ -920,6 +912,7 @@ void CGameState::init(StartInfo * si)
} }
//picking random factions for players //picking random factions for players
tlog4 << "\tPicking random factions for players";
for(std::map<int, PlayerSettings>::iterator it = scenarioOps->playerInfos.begin(); for(std::map<int, PlayerSettings>::iterator it = scenarioOps->playerInfos.begin();
it != scenarioOps->playerInfos.end(); ++it) it != scenarioOps->playerInfos.end(); ++it)
{ {
@ -935,6 +928,7 @@ void CGameState::init(StartInfo * si)
} }
//randomizing objects //randomizing objects
tlog4 << "\tRandomizing objects";
BOOST_FOREACH(CGObjectInstance *obj, map->objects) BOOST_FOREACH(CGObjectInstance *obj, map->objects)
{ {
randomizeObject(obj); randomizeObject(obj);
@ -953,6 +947,7 @@ void CGameState::init(StartInfo * si)
//std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl; //std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl;
/*********creating players entries in gs****************************************/ /*********creating players entries in gs****************************************/
tlog4 << "\tCreating player entries in gs";
for(std::map<int, PlayerSettings>::iterator it = scenarioOps->playerInfos.begin(); for(std::map<int, PlayerSettings>::iterator it = scenarioOps->playerInfos.begin();
it != scenarioOps->playerInfos.end(); ++it) it != scenarioOps->playerInfos.end(); ++it)
{ {
@ -966,6 +961,7 @@ void CGameState::init(StartInfo * si)
} }
/*********give starting hero****************************************/ /*********give starting hero****************************************/
tlog4 << "\tGiving starting hero";
for(int i=0;i<GameConstants::PLAYER_LIMIT;i++) for(int i=0;i<GameConstants::PLAYER_LIMIT;i++)
{ {
const PlayerInfo &p = map->players[i]; const PlayerInfo &p = map->players[i];
@ -989,7 +985,7 @@ void CGameState::init(StartInfo * si)
} }
/*************************replace hero placeholders*****************************/ /*************************replace hero placeholders*****************************/
tlog4 << "\tReplacing hero placeholders";
if (scenarioOps->campState) if (scenarioOps->campState)
{ {
auto campaign = scenarioOps->campState; auto campaign = scenarioOps->campState;
@ -997,7 +993,7 @@ void CGameState::init(StartInfo * si)
std::vector<CGHeroInstance *> Xheroes; std::vector<CGHeroInstance *> Xheroes;
if (bonus.type == 8) //hero crossover if (bonus.type == CScenarioTravel::STravelBonus::PLAYER_PREV_SCENARIO) //hero crossover
{ {
Xheroes = campaign->camp->scenarios[bonus.info2].crossoverHeroes; Xheroes = campaign->camp->scenarios[bonus.info2].crossoverHeroes;
} }
@ -1020,7 +1016,7 @@ void CGameState::init(StartInfo * si)
if (ghi->subID == hp->subID) if (ghi->subID == hp->subID)
{ {
found = true; found = true;
HLP::replaceHero(this, g, ghi); replaceHero(g, ghi);
Xheroes -= ghi; Xheroes -= ghi;
break; break;
} }
@ -1034,7 +1030,10 @@ void CGameState::init(StartInfo * si)
//selecting heroes by power //selecting heroes by power
std::sort(Xheroes.begin(), Xheroes.end(), HLP::heroPowerSorter); std::sort(Xheroes.begin(), Xheroes.end(), [](const CGHeroInstance * a, const CGHeroInstance * b)
{
return a->getHeroStrength() > b->getHeroStrength();
}); //sort, descending strength
for(int g=0; g<map->objects.size(); ++g) for(int g=0; g<map->objects.size(); ++g)
{ {
CGObjectInstance * obj = map->objects[g]; CGObjectInstance * obj = map->objects[g];
@ -1047,7 +1046,7 @@ void CGameState::init(StartInfo * si)
if (hp->subID == 0xFF) //select by power if (hp->subID == 0xFF) //select by power
{ {
if(Xheroes.size() > hp->power - 1) if(Xheroes.size() > hp->power - 1)
HLP::replaceHero(this, g, Xheroes[hp->power - 1]); replaceHero(g, Xheroes[hp->power - 1]);
else else
tlog2 << "Warning, to hero to replace!\n"; tlog2 << "Warning, to hero to replace!\n";
//we don't have to remove hero from Xheroes because it would destroy the order and duplicates shouldn't happen //we don't have to remove hero from Xheroes because it would destroy the order and duplicates shouldn't happen
@ -1056,6 +1055,7 @@ void CGameState::init(StartInfo * si)
} }
/******************RESOURCES****************************************************/ /******************RESOURCES****************************************************/
tlog4 << "\tSetting up resources";
const JsonNode config(ResourceID("config/startres.json")); const JsonNode config(ResourceID("config/startres.json"));
const JsonVector &vector = config["difficulty"].Vector(); const JsonVector &vector = config["difficulty"].Vector();
const JsonNode &level = vector[scenarioOps->difficulty]; const JsonNode &level = vector[scenarioOps->difficulty];
@ -1077,9 +1077,9 @@ void CGameState::init(StartInfo * si)
if (scenarioOps->mode == StartInfo::CAMPAIGN) if (scenarioOps->mode == StartInfo::CAMPAIGN)
{ {
CScenarioTravel::STravelBonus chosenBonus = scenarioOps->campState->getBonusForCurrentMap(); CScenarioTravel::STravelBonus chosenBonus = scenarioOps->campState->getBonusForCurrentMap();
if(chosenBonus.type == 7) //resource if(chosenBonus.type == CScenarioTravel::STravelBonus::RESOURCE)
{ {
std::vector<const PlayerSettings *> people = HLP::getHumanPlayerInfo(scenarioOps); //players we will give resource bonus std::vector<const PlayerSettings *> people = getHumanPlayerInfo(); //players we will give resource bonus
BOOST_FOREACH(const PlayerSettings *ps, people) BOOST_FOREACH(const PlayerSettings *ps, people)
{ {
std::vector<int> res; //resources we will give std::vector<int> res; //resources we will give
@ -1109,6 +1109,7 @@ void CGameState::init(StartInfo * si)
/*************************HEROES************************************************/ /*************************HEROES************************************************/
tlog4 << "\tSetting up heroes";
std::set<int> hids; //hero ids to create pool std::set<int> hids; //hero ids to create pool
for(ui32 i=0; i<map->allowedHeroes.size(); i++) //add to hids all allowed heroes for(ui32 i=0; i<map->allowedHeroes.size(); i++) //add to hids all allowed heroes
@ -1190,7 +1191,7 @@ void CGameState::init(StartInfo * si)
if(maxB < 0) if(maxB < 0)
tlog2 << "Warning - cannot give bonus to hero cause there are no heroes!\n"; tlog2 << "Warning - cannot give bonus to hero cause there are no heroes!\n";
else else
HLP::giveCampaignBonusToHero(heroes[maxB], scenarioOps, scenarioOps->campState->getCurrentScenario().travelOptions, this); giveCampaignBonusToHero(heroes[maxB]);
} }
else //specific hero else //specific hero
{ {
@ -1198,7 +1199,7 @@ void CGameState::init(StartInfo * si)
{ {
if (heroes[b]->subID == chosenBonus.info1) if (heroes[b]->subID == chosenBonus.info1)
{ {
HLP::giveCampaignBonusToHero(heroes[b], scenarioOps, scenarioOps->campState->getCurrentScenario().travelOptions, this); giveCampaignBonusToHero(heroes[b]);
break; break;
} }
} }
@ -1207,6 +1208,7 @@ void CGameState::init(StartInfo * si)
} }
/*************************FOG**OF**WAR******************************************/ /*************************FOG**OF**WAR******************************************/
tlog4 << "\tFog of war";
for(std::map<ui8, TeamState>::iterator k=teams.begin(); k!=teams.end(); ++k) for(std::map<ui8, TeamState>::iterator k=teams.begin(); k!=teams.end(); ++k)
{ {
k->second.fogOfWarMap.resize(map->width); k->second.fogOfWarMap.resize(map->width);
@ -1235,6 +1237,7 @@ void CGameState::init(StartInfo * si)
} }
} }
tlog4 << "\tStarting bonuses";
for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k) for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
{ {
//starting bonus //starting bonus
@ -1276,6 +1279,7 @@ void CGameState::init(StartInfo * si)
} }
} }
/****************************TOWNS************************************************/ /****************************TOWNS************************************************/
tlog4 << "\tTowns";
for ( int i=0; i<4; i++) for ( int i=0; i<4; i++)
CGTownInstance::universitySkills.push_back(14+i);//skills for university CGTownInstance::universitySkills.push_back(14+i);//skills for university
@ -1375,7 +1379,7 @@ void CGameState::init(StartInfo * si)
{ {
CScenarioTravel::STravelBonus chosenBonus = scenarioOps->campState->getBonusForCurrentMap(); CScenarioTravel::STravelBonus chosenBonus = scenarioOps->campState->getBonusForCurrentMap();
if (chosenBonus.type == 2) if (chosenBonus.type == CScenarioTravel::STravelBonus::BUILDING)
{ {
for (int g=0; g<map->towns.size(); ++g) for (int g=0; g<map->towns.size(); ++g)
{ {
@ -1396,7 +1400,7 @@ void CGameState::init(StartInfo * si)
} }
} }
tlog4 << "\tObject initialization";
objCaller->preInit(); objCaller->preInit();
BOOST_FOREACH(CGObjectInstance *obj, map->objects) BOOST_FOREACH(CGObjectInstance *obj, map->objects)
{ {
@ -1448,6 +1452,7 @@ void CGameState::init(StartInfo * si)
} }
tlog4 << "\tChecking objectives";
map->checkForObjectives(); //needs to be run when all objects are properly placed map->checkForObjectives(); //needs to be run when all objects are properly placed
int seedAfterInit = ran(); int seedAfterInit = ran();