2008-06-13 00:08:04 +03:00
# define VCMI_DLL
2008-01-09 19:21:31 +02:00
# include "../stdafx.h"
2007-06-08 22:56:35 +03:00
# include "CCreatureHandler.h"
2007-08-29 15:18:31 +03:00
# include "CLodHandler.h"
2007-10-15 23:59:17 +03:00
# include <sstream>
2008-08-30 00:41:32 +03:00
# include <boost/assign/std/set.hpp>
2007-10-15 23:59:17 +03:00
# include <boost/assign/std/vector.hpp>
2010-05-02 21:20:26 +03:00
# include <boost/assign/std/list.hpp>
2009-07-07 06:34:23 +03:00
# include <boost/assign/list_of.hpp>
2007-10-15 23:59:17 +03:00
# include <boost/algorithm/string.hpp>
2008-04-14 21:24:46 +03:00
# include <boost/algorithm/string/find.hpp>
2007-10-15 23:59:17 +03:00
# include <boost/algorithm/string/replace.hpp>
2008-06-17 20:48:32 +03:00
# include "../lib/VCMI_Lib.h"
2010-08-24 17:26:57 +03:00
# include "../lib/CGameState.h"
2011-02-06 10:32:05 +02:00
# include <boost/foreach.hpp>
2009-04-15 17:03:31 +03:00
2008-08-30 00:41:32 +03:00
using namespace boost : : assign ;
2008-06-13 00:08:04 +03:00
extern CLodHandler * bitmaph ;
2009-04-15 17:03:31 +03:00
/*
* CCreatureHandler . cpp , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
2009-05-24 01:57:39 +03:00
static std : : vector < int > getMindSpells ( )
2009-05-14 20:26:55 +03:00
{
std : : vector < int > ret ;
ret . push_back ( 50 ) ; //sorrow
ret . push_back ( 59 ) ; //berserk
ret . push_back ( 60 ) ; //hypnotize
ret . push_back ( 61 ) ; //forgetfulness
2009-08-24 20:40:20 +03:00
ret . push_back ( 62 ) ; //blind
2009-05-14 20:26:55 +03:00
return ret ;
}
2008-06-17 20:48:32 +03:00
CCreatureHandler : : CCreatureHandler ( )
{
VLC - > creh = this ;
2009-08-24 20:40:20 +03:00
// Set the faction alignments to the defaults:
// Good: Castle, Rampart, Tower // Evil: Inferno, Necropolis, Dungeon
// Neutral: Stronghold, Fortess, Conflux
factionAlignments + = 1 , 1 , 1 , - 1 , - 1 , - 1 , 0 , 0 , 0 ;
2010-08-29 10:49:04 +03:00
doubledCreatures + = 4 , 14 , 20 , 28 , 42 , 44 , 60 , 70 , 72 , 85 , 86 , 100 , 104 ; //according to Strategija
2008-06-17 20:48:32 +03:00
}
2009-08-24 20:40:20 +03:00
2008-09-24 19:25:14 +03:00
int CCreature : : getQuantityID ( const int & quantity )
2008-02-25 01:06:27 +02:00
{
if ( quantity < 5 )
return 0 ;
if ( quantity < 10 )
return 1 ;
if ( quantity < 20 )
return 2 ;
if ( quantity < 50 )
return 3 ;
if ( quantity < 100 )
return 4 ;
if ( quantity < 250 )
return 5 ;
if ( quantity < 500 )
return 5 ;
if ( quantity < 1000 )
return 6 ;
if ( quantity < 4000 )
return 7 ;
return 8 ;
}
2008-09-24 19:25:14 +03:00
bool CCreature : : isDoubleWide ( ) const
2008-04-14 21:24:46 +03:00
{
2010-05-02 21:20:26 +03:00
return doubleWide ;
2008-04-14 21:24:46 +03:00
}
2008-09-24 19:25:14 +03:00
bool CCreature : : isFlying ( ) const
2008-04-14 21:24:46 +03:00
{
2010-11-19 00:06:56 +02:00
return hasBonusOfType ( Bonus : : FLYING ) ;
2008-04-14 21:24:46 +03:00
}
2009-05-08 19:55:04 +03:00
2008-09-24 19:25:14 +03:00
bool CCreature : : isShooting ( ) const
2008-08-02 18:08:03 +03:00
{
2010-11-19 00:06:56 +02:00
return hasBonusOfType ( Bonus : : SHOOTER ) ;
2008-08-02 18:08:03 +03:00
}
2009-05-08 19:55:04 +03:00
2009-04-16 17:01:27 +03:00
bool CCreature : : isUndead ( ) const
{
2010-11-19 00:06:56 +02:00
return hasBonusOfType ( Bonus : : UNDEAD ) ;
2009-04-16 17:01:27 +03:00
}
2009-05-08 19:55:04 +03:00
2009-08-24 20:40:20 +03:00
/**
* Determines if the creature is of a good alignment .
* @ return true if the creture is good , false otherwise .
*/
bool CCreature : : isGood ( ) const
{
return VLC - > creh - > isGood ( faction ) ;
}
/**
* Determines if the creature is of an evil alignment .
* @ return true if the creature is evil , false otherwise .
*/
bool CCreature : : isEvil ( ) const
{
return VLC - > creh - > isEvil ( faction ) ;
}
2008-08-01 14:21:15 +03:00
si32 CCreature : : maxAmount ( const std : : vector < si32 > & res ) const //how many creatures can be bought
2008-05-12 08:46:04 +03:00
{
int ret = 2147483645 ;
int resAmnt = std : : min ( res . size ( ) , cost . size ( ) ) ;
for ( int i = 0 ; i < resAmnt ; i + + )
if ( cost [ i ] )
2008-08-01 14:21:15 +03:00
ret = std : : min ( ret , ( int ) ( res [ i ] / cost [ i ] ) ) ;
2008-05-12 08:46:04 +03:00
return ret ;
}
2008-04-14 21:24:46 +03:00
2010-05-02 21:20:26 +03:00
CCreature : : CCreature ( )
{
doubleWide = false ;
2010-08-26 10:23:08 +03:00
nodeType = CBonusSystemNode : : CREATURE ;
2010-05-02 21:20:26 +03:00
}
void CCreature : : addBonus ( int val , int type , int subtype /*= -1*/ )
{
2010-11-20 02:03:31 +02:00
Bonus * added = new Bonus ( Bonus : : PERMANENT , type , Bonus : : CREATURE_ABILITY , val , idNumber , subtype , Bonus : : BASE_NUMBER ) ;
2010-11-19 00:06:56 +02:00
addNewBonus ( added ) ;
2010-05-02 21:20:26 +03:00
}
2010-11-13 22:26:15 +02:00
// void CCreature::getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const
// {
// out.insert (VLC->creh->globalEffects);
// }
2010-07-12 13:20:25 +03:00
bool CCreature : : isMyUpgrade ( const CCreature * anotherCre ) const
{
//TODO upgrade of upgrade?
return vstd : : contains ( upgrades , anotherCre - > idNumber ) ;
}
2010-11-27 22:17:28 +02:00
bool CCreature : : valid ( ) const
{
return this = = VLC - > creh - > creatures [ idNumber ] ;
}
2010-12-29 23:04:22 +02:00
std : : string CCreature : : nodeName ( ) const
{
return " Type of creature " + namePl ;
}
2009-06-28 17:57:00 +03:00
int readNumber ( int & befi , int & i , int andame , std : : string & buf ) //helper function for void CCreatureHandler::loadCreatures() and loadUnitAnimInfo()
2009-06-28 16:49:39 +03:00
{
befi = i ;
2010-10-25 22:37:21 +03:00
for ( ; i < andame ; + + i )
2009-06-28 16:49:39 +03:00
{
if ( buf [ i ] = = ' \t ' )
break ;
}
std : : string tmp = buf . substr ( befi , i - befi ) ;
int ret = atoi ( buf . substr ( befi , i - befi ) . c_str ( ) ) ;
+ + i ;
return ret ;
}
2009-06-28 17:57:00 +03:00
float readFloat ( int & befi , int & i , int andame , std : : string & buf ) //helper function for void CCreatureHandler::loadUnitAnimInfo()
{
befi = i ;
2010-10-25 22:37:21 +03:00
for ( ; i < andame ; + + i )
2009-06-28 17:57:00 +03:00
{
if ( buf [ i ] = = ' \t ' )
break ;
}
std : : string tmp = buf . substr ( befi , i - befi ) ;
float ret = atof ( buf . substr ( befi , i - befi ) . c_str ( ) ) ;
+ + i ;
return ret ;
}
2009-08-24 20:40:20 +03:00
/**
* Determines if a faction is good .
* @ param ID of the faction .
* @ return true if the faction is good , false otherwise .
*/
bool CCreatureHandler : : isGood ( si8 faction ) const
{
return faction ! = - 1 & & factionAlignments [ faction ] = = 1 ;
}
/**
* Determines if a faction is evil .
* @ param ID of the faction .
* @ return true if the faction is evil , false otherwise .
*/
bool CCreatureHandler : : isEvil ( si8 faction ) const
{
return faction ! = - 1 & & factionAlignments [ faction ] = = - 1 ;
}
2007-06-08 22:56:35 +03:00
void CCreatureHandler : : loadCreatures ( )
{
2008-09-01 03:25:36 +03:00
notUsedMonsters + = 122 , 124 , 126 , 128 , 145 , 146 , 147 , 148 , 149 , 160 , 161 , 162 , 163 , 174 , 175 , 176 , 177 , 178 , 179 , 180 , 181 , 182 , 183 , 184 , 185 , 186 , 187 , 188 , 189 , 190 , 191 ;
2009-06-28 16:49:39 +03:00
tlog5 < < " \t \t Reading config/cr_abils.txt and ZCRTRAIT.TXT " < < std : : endl ;
bool useCreAbilsFromZCRTRAIT = true ;
////////////reading cr_abils.txt ///////////////////
2009-10-04 05:02:45 +03:00
std : : ifstream abils ( DATA_DIR " /config/cr_abils.txt " , std : : ios : : in | std : : ios : : binary ) ; //this file is not in lod
2009-06-28 16:49:39 +03:00
const int MAX_LINE_SIZE = 1000 ;
char abilLine [ MAX_LINE_SIZE + 1 ] ;
for ( int i = 0 ; i < 5 ; + + i ) //removing 5 comment lines
{
abils . getline ( abilLine , MAX_LINE_SIZE ) ;
}
//reading first line (determining if we should use creature abilities from ZCRTRAIT.TXT)
abils . getline ( abilLine , MAX_LINE_SIZE ) ;
useCreAbilsFromZCRTRAIT = atoi ( abilLine ) ;
////////////reading ZCRTRAIT.TXT ///////////////////
2008-06-12 09:45:51 +03:00
std : : string buf = bitmaph - > getTextFile ( " ZCRTRAIT.TXT " ) ;
2007-07-16 17:42:44 +03:00
int andame = buf . size ( ) ;
2007-06-10 21:04:15 +03:00
int i = 0 ; //buf iterator
int hmcr = 0 ;
2010-10-25 22:37:21 +03:00
for ( ; i < andame ; + + i )
2007-06-08 22:56:35 +03:00
{
2007-06-10 21:04:15 +03:00
if ( buf [ i ] = = ' \r ' )
+ + hmcr ;
if ( hmcr = = 2 )
break ;
2007-06-08 22:56:35 +03:00
}
2007-06-10 21:04:15 +03:00
i + = 2 ;
while ( i < buf . size ( ) )
2007-06-08 22:56:35 +03:00
{
2010-05-02 21:20:26 +03:00
CCreature & ncre = * new CCreature ;
ncre . idNumber = creatures . size ( ) ;
2008-04-04 20:30:53 +03:00
ncre . cost . resize ( RESOURCE_QUANTITY ) ;
2008-02-05 05:56:45 +02:00
ncre . level = 0 ;
2009-04-26 02:31:39 +03:00
2007-06-10 21:04:15 +03:00
int befi = i ;
2010-10-25 22:37:21 +03:00
for ( ; i < andame ; + + i )
2007-06-08 22:56:35 +03:00
{
2007-06-10 21:04:15 +03:00
if ( buf [ i ] = = ' \t ' )
break ;
2007-06-08 22:56:35 +03:00
}
2007-06-10 21:04:15 +03:00
ncre . nameSing = buf . substr ( befi , i - befi ) ;
+ + i ;
2007-06-08 22:56:35 +03:00
2007-06-10 21:04:15 +03:00
befi = i ;
2010-10-25 22:37:21 +03:00
for ( ; i < andame ; + + i )
2007-06-08 22:56:35 +03:00
{
2007-06-10 21:04:15 +03:00
if ( buf [ i ] = = ' \t ' )
break ;
2007-06-08 22:56:35 +03:00
}
2007-06-10 21:04:15 +03:00
ncre . namePl = buf . substr ( befi , i - befi ) ;
+ + i ;
2007-06-08 22:56:35 +03:00
2009-06-28 16:49:39 +03:00
for ( int v = 0 ; v < 7 ; + + v )
2007-06-08 22:56:35 +03:00
{
2009-06-28 16:49:39 +03:00
ncre . cost [ v ] = readNumber ( befi , i , andame , buf ) ;
2007-06-08 22:56:35 +03:00
}
2009-06-28 16:49:39 +03:00
ncre . fightValue = readNumber ( befi , i , andame , buf ) ;
ncre . AIValue = readNumber ( befi , i , andame , buf ) ;
ncre . growth = readNumber ( befi , i , andame , buf ) ;
ncre . hordeGrowth = readNumber ( befi , i , andame , buf ) ;
2010-05-02 21:20:26 +03:00
2009-06-28 16:49:39 +03:00
ncre . hitPoints = readNumber ( befi , i , andame , buf ) ;
2010-05-02 21:20:26 +03:00
ncre . addBonus ( ncre . hitPoints , Bonus : : STACK_HEALTH ) ;
2009-06-28 16:49:39 +03:00
ncre . speed = readNumber ( befi , i , andame , buf ) ;
2010-05-02 21:20:26 +03:00
ncre . addBonus ( ncre . speed , Bonus : : STACKS_SPEED ) ;
2009-06-28 16:49:39 +03:00
ncre . attack = readNumber ( befi , i , andame , buf ) ;
2010-05-02 21:20:26 +03:00
ncre . addBonus ( ncre . attack , Bonus : : PRIMARY_SKILL , PrimarySkill : : ATTACK ) ;
2009-06-28 16:49:39 +03:00
ncre . defence = readNumber ( befi , i , andame , buf ) ;
2010-05-02 21:20:26 +03:00
ncre . addBonus ( ncre . defence , Bonus : : PRIMARY_SKILL , PrimarySkill : : DEFENSE ) ;
2010-08-30 21:06:17 +03:00
ncre . damageMin = readNumber ( befi , i , andame , buf ) ; //not used anymore?
ncre . addBonus ( ncre . damageMin , Bonus : : CREATURE_DAMAGE , 1 ) ;
2009-06-28 16:49:39 +03:00
ncre . damageMax = readNumber ( befi , i , andame , buf ) ;
2010-08-30 21:06:17 +03:00
ncre . addBonus ( ncre . damageMax , Bonus : : CREATURE_DAMAGE , 2 ) ;
2010-05-02 21:20:26 +03:00
2009-06-28 16:49:39 +03:00
ncre . shots = readNumber ( befi , i , andame , buf ) ;
ncre . spells = readNumber ( befi , i , andame , buf ) ;
ncre . ammMin = readNumber ( befi , i , andame , buf ) ;
ncre . ammMax = readNumber ( befi , i , andame , buf ) ;
2007-06-08 22:56:35 +03:00
2007-06-10 21:04:15 +03:00
befi = i ;
2010-10-25 22:37:21 +03:00
for ( ; i < andame ; + + i )
2007-06-08 22:56:35 +03:00
{
2007-06-10 21:04:15 +03:00
if ( buf [ i ] = = ' \t ' )
break ;
2007-06-08 22:56:35 +03:00
}
2007-06-10 21:04:15 +03:00
ncre . abilityText = buf . substr ( befi , i - befi ) ;
+ + i ;
2007-06-08 22:56:35 +03:00
2007-06-10 21:04:15 +03:00
befi = i ;
2010-10-25 22:37:21 +03:00
for ( ; i < andame ; + + i )
2007-06-08 22:56:35 +03:00
{
2007-06-10 21:04:15 +03:00
if ( buf [ i ] = = ' \r ' )
break ;
2007-06-08 22:56:35 +03:00
}
2007-06-10 21:04:15 +03:00
ncre . abilityRefs = buf . substr ( befi , i - befi ) ;
i + = 2 ;
2009-06-28 16:49:39 +03:00
if ( useCreAbilsFromZCRTRAIT )
{ //adding abilities from ZCRTRAIT.TXT
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " DOUBLE_WIDE " ) )
2010-05-02 21:20:26 +03:00
ncre . doubleWide = true ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " FLYING_ARMY " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : FLYING ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " SHOOTING_ARMY " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : SHOOTER ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " SIEGE_WEAPON " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : SIEGE_WEAPON ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " const_two_attacks " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 1 , Bonus : : ADDITIONAL_ATTACK ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " const_free_attack " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : BLOCKS_RETALIATION ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " IS_UNDEAD " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : UNDEAD ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " const_no_melee_penalty " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : NO_MELEE_PENALTY ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " const_jousting " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : JOUSTING ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " const_raises_morale " ) )
2010-05-02 21:20:26 +03:00
{
ncre . addBonus ( + 1 , Bonus : : MORALE ) ; ;
2010-11-19 00:06:56 +02:00
ncre . bonuses . back ( ) - > effectRange = Bonus : : ONLY_ALLIED_ARMY ;
2010-05-02 21:20:26 +03:00
}
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " const_lowers_morale " ) )
2010-05-02 21:20:26 +03:00
{
ncre . addBonus ( - 1 , Bonus : : MORALE ) ; ;
2010-11-19 00:06:56 +02:00
ncre . bonuses . back ( ) - > effectRange = Bonus : : ONLY_ENEMY_ARMY ;
2010-05-02 21:20:26 +03:00
}
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " KING_1 " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : KING1 ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " KING_2 " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : KING2 ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " KING_3 " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : KING3 ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " const_no_wall_penalty " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : NO_WALL_PENALTY ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " CATAPULT " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : CATAPULT ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " MULTI_HEADED " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : ATTACKS_ALL_ADJACENT ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " IMMUNE_TO_MIND_SPELLS " ) )
2009-05-15 15:07:55 +03:00
{
2009-06-28 16:49:39 +03:00
std : : vector < int > mindSpells = getMindSpells ( ) ;
for ( int g = 0 ; g < mindSpells . size ( ) ; + + g )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : SPELL_IMMUNITY , mindSpells [ g ] ) ; //giants are immune to mind spells
2009-05-15 15:07:55 +03:00
}
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " IMMUNE_TO_FIRE_SPELLS " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : FIRE_IMMUNITY ) ;
2009-06-28 16:49:39 +03:00
if ( boost : : algorithm : : find_first ( ncre . abilityRefs , " HAS_EXTENDED_ATTACK " ) )
2010-05-02 21:20:26 +03:00
ncre . addBonus ( 0 , Bonus : : TWO_HEX_ATTACK_BREATH ) ; ;
2009-05-15 15:07:55 +03:00
}
2009-05-13 23:40:23 +03:00
2007-06-13 23:17:48 +03:00
if ( ncre . nameSing ! = std : : string ( " " ) & & ncre . namePl ! = std : : string ( " " ) )
{
ncre . idNumber = creatures . size ( ) ;
2010-05-02 21:20:26 +03:00
creatures . push_back ( & ncre ) ;
2007-06-13 23:17:48 +03:00
}
2007-06-08 22:56:35 +03:00
}
2010-07-12 13:20:25 +03:00
2009-06-28 16:49:39 +03:00
////second part of reading cr_abils.txt////
bool contReading = true ;
while ( contReading ) //main reading loop
{
abils . getline ( abilLine , MAX_LINE_SIZE ) ;
std : : istringstream reader ( abilLine ) ;
char command ;
reader > > command ;
switch ( command )
{
case ' + ' : //add new ability
{
int creatureID ;
2010-11-20 02:03:31 +02:00
Bonus * nsf = new Bonus ( ) ;
2009-06-28 16:49:39 +03:00
si32 buf ;
2009-07-07 06:34:23 +03:00
std : : string type ;
2009-06-28 16:49:39 +03:00
reader > > creatureID ;
2009-07-07 06:34:23 +03:00
reader > > type ;
2010-05-02 21:20:26 +03:00
2010-07-12 13:20:25 +03:00
std : : map < std : : string , int > : : const_iterator it = bonusNameMap . find ( type ) ;
2010-05-02 21:20:26 +03:00
CCreature * cre = creatures [ creatureID ] ;
2010-07-12 13:20:25 +03:00
if ( it = = bonusNameMap . end ( ) )
2010-05-02 21:20:26 +03:00
{
if ( type = = " DOUBLE_WIDE " )
cre - > doubleWide = true ;
else if ( type = = " ENEMY_MORALE_DECREASING " )
{
2010-11-19 00:06:56 +02:00
cre - > addBonus ( - 1 , Bonus : : MORALE ) ;
cre - > bonuses . back ( ) - > effectRange = Bonus : : ONLY_ENEMY_ARMY ;
2010-05-02 21:20:26 +03:00
}
else if ( type = = " ENEMY_LUCK_DECREASING " )
{
2010-11-19 00:06:56 +02:00
cre - > addBonus ( - 1 , Bonus : : LUCK ) ;
cre - > bonuses . back ( ) - > effectRange = Bonus : : ONLY_ENEMY_ARMY ;
2010-05-02 21:20:26 +03:00
}
else
tlog1 < < " Error: invalid type " < < type < < " in cr_abils.txt " < < std : : endl ;
2009-07-07 06:34:23 +03:00
break ;
}
2010-11-20 02:03:31 +02:00
nsf - > type = it - > second ;
reader > > buf ; nsf - > val = buf ;
reader > > buf ; nsf - > subtype = buf ;
reader > > buf ; nsf - > additionalInfo = buf ;
nsf - > source = Bonus : : CREATURE_ABILITY ;
nsf - > id = cre - > idNumber ;
nsf - > duration = Bonus : : ONE_BATTLE ;
nsf - > turnsRemain = 0 ;
2009-06-28 16:49:39 +03:00
2010-11-19 00:06:56 +02:00
cre - > addNewBonus ( nsf ) ;
2009-06-28 16:49:39 +03:00
break ;
}
case ' - ' : //remove ability
{
int creatureID ;
2009-08-05 15:46:08 +03:00
std : : string type ;
2009-06-28 16:49:39 +03:00
reader > > creatureID ;
reader > > type ;
2010-07-12 13:20:25 +03:00
std : : map < std : : string , int > : : const_iterator it = bonusNameMap . find ( type ) ;
if ( it = = bonusNameMap . end ( ) )
2009-08-05 15:46:08 +03:00
{
2010-05-02 21:20:26 +03:00
if ( type = = " DOUBLE_WIDE " )
creatures [ creatureID ] - > doubleWide = false ;
else
tlog1 < < " Error: invalid type " < < type < < " in cr_abils.txt " < < std : : endl ;
2009-08-05 15:46:08 +03:00
break ;
}
int typeNo = it - > second ;
2010-05-02 21:20:26 +03:00
Bonus : : BonusType ecf = static_cast < Bonus : : BonusType > ( typeNo ) ;
2009-06-28 16:49:39 +03:00
2010-11-19 00:06:56 +02:00
Bonus * b = creatures [ creatureID ] - > getBonus ( Selector : : type ( ecf ) ) ;
creatures [ creatureID ] - > removeBonus ( b ) ;
2009-06-28 16:49:39 +03:00
break ;
}
case ' 0 ' : //end reading
{
contReading = false ;
break ;
}
default : //invalid command
{
tlog1 < < " Parse error in file config/cr_abils.txt " < < std : : endl ;
break ;
}
}
}
abils . close ( ) ;
2008-11-01 00:41:22 +02:00
tlog5 < < " \t \t Reading config/crerefnam.txt " < < std : : endl ;
2007-10-17 01:39:11 +03:00
//loading reference names
2009-10-04 05:02:45 +03:00
std : : ifstream ifs ( DATA_DIR " /config/crerefnam.txt " ) ;
2007-10-15 23:59:17 +03:00
int tempi ;
std : : string temps ;
for ( ; ; )
2007-06-18 13:49:06 +03:00
{
2007-10-15 23:59:17 +03:00
ifs > > tempi > > temps ;
if ( tempi > = creatures . size ( ) )
2007-06-18 13:49:06 +03:00
break ;
2007-10-15 23:59:17 +03:00
boost : : assign : : insert ( nameToID ) ( temps , tempi ) ;
2010-05-02 21:20:26 +03:00
creatures [ tempi ] - > nameRef = temps ;
2007-06-18 13:49:06 +03:00
}
2007-10-15 23:59:17 +03:00
ifs . close ( ) ;
2008-02-05 05:56:45 +02:00
ifs . clear ( ) ;
2010-12-17 20:47:07 +02:00
for ( i = 1 ; i < = CRE_LEVELS ; i + + )
levelCreatures [ i ] ;
2008-11-01 00:41:22 +02:00
tlog5 < < " \t \t Reading config/monsters.txt " < < std : : endl ;
2009-10-04 05:02:45 +03:00
ifs . open ( DATA_DIR " /config/monsters.txt " ) ;
2008-02-05 05:56:45 +02:00
{
while ( ! ifs . eof ( ) )
{
int id , lvl ;
ifs > > id > > lvl ;
if ( lvl > 0 )
{
2010-05-02 21:20:26 +03:00
creatures [ id ] - > level = lvl ;
levelCreatures [ lvl ] . push_back ( creatures [ id ] ) ;
2008-02-05 05:56:45 +02:00
}
}
}
2008-04-04 20:30:53 +03:00
ifs . close ( ) ;
ifs . clear ( ) ;
2008-11-01 00:41:22 +02:00
tlog5 < < " \t \t Reading config/cr_factions.txt " < < std : : endl ;
2009-10-04 05:02:45 +03:00
ifs . open ( DATA_DIR " /config/cr_factions.txt " ) ;
2008-04-04 20:30:53 +03:00
while ( ! ifs . eof ( ) )
{
int id , fact ;
ifs > > id > > fact ;
2010-05-02 21:20:26 +03:00
creatures [ id ] - > faction = fact ;
2008-04-04 20:30:53 +03:00
}
ifs . close ( ) ;
ifs . clear ( ) ;
2007-10-17 01:39:11 +03:00
2008-11-01 00:41:22 +02:00
tlog5 < < " \t \t Reading config/cr_upgrade_list.txt " < < std : : endl ;
2009-10-04 05:02:45 +03:00
ifs . open ( DATA_DIR " /config/cr_upgrade_list.txt " ) ;
2008-05-31 23:37:54 +03:00
while ( ! ifs . eof ( ) )
{
int id , up ;
ifs > > id > > up ;
2010-05-02 21:20:26 +03:00
creatures [ id ] - > upgrades . insert ( up ) ;
2008-05-31 23:37:54 +03:00
}
ifs . close ( ) ;
ifs . clear ( ) ;
2008-08-02 18:08:03 +03:00
2008-03-05 19:01:41 +02:00
//loading unit animation def names
2008-11-01 00:41:22 +02:00
tlog5 < < " \t \t Reading config/CREDEFS.TXT " < < std : : endl ;
2009-10-04 05:02:45 +03:00
std : : ifstream inp ( DATA_DIR " /config/CREDEFS.TXT " , std : : ios : : in | std : : ios : : binary ) ; //this file is not in lod
2008-03-05 19:01:41 +02:00
inp . seekg ( 0 , std : : ios : : end ) ; // na koniec
int andame2 = inp . tellg ( ) ; // read length
inp . seekg ( 0 , std : : ios : : beg ) ; // wracamy na poczatek
2009-04-13 21:52:20 +03:00
char * bufor = new char [ andame2 + 1 ] ; // allocate memory
2008-03-05 19:01:41 +02:00
inp . read ( ( char * ) bufor , andame2 ) ; // read map file to buffer
inp . close ( ) ;
2009-04-13 21:52:20 +03:00
bufor [ andame2 ] = 0 ;
2008-03-05 19:01:41 +02:00
buf = std : : string ( bufor ) ;
2008-08-02 18:08:03 +03:00
delete [ ] bufor ;
2008-03-05 19:01:41 +02:00
i = 0 ; //buf iterator
hmcr = 0 ;
2010-10-25 22:37:21 +03:00
for ( ; i < andame2 ; + + i ) //omitting rubbish
2008-03-05 19:01:41 +02:00
{
if ( buf [ i ] = = ' \r ' )
break ;
}
i + = 2 ;
2008-11-01 00:41:22 +02:00
tlog5 < < " We have " < < creatures . size ( ) < < " creatures \n " ;
for ( int s = 0 ; s < creatures . size ( ) ; + + s )
2008-03-05 19:01:41 +02:00
{
2008-11-01 00:41:22 +02:00
//tlog5 <<"\t\t\t" << s <<". Reading defname. \n";
2008-03-05 19:01:41 +02:00
int befi = i ;
std : : string rub ;
2010-10-25 22:37:21 +03:00
for ( ; i < andame2 ; + + i )
2008-03-05 19:01:41 +02:00
{
if ( buf [ i ] = = ' ' )
break ;
}
rub = buf . substr ( befi , i - befi ) ;
+ + i ;
befi = i ;
2010-10-25 22:37:21 +03:00
for ( ; i < andame2 ; + + i )
2008-03-05 19:01:41 +02:00
{
if ( buf [ i ] = = ' \r ' )
break ;
}
std : : string defName = buf . substr ( befi , i - befi ) ;
2010-05-02 21:20:26 +03:00
creatures [ s ] - > animDefName = defName ;
2008-03-05 19:01:41 +02:00
}
2008-11-01 00:41:22 +02:00
tlog5 < < " \t \t Reading CRANIM.TXT.txt " < < std : : endl ;
2008-03-05 19:01:41 +02:00
loadAnimationInfo ( ) ;
2008-08-02 18:08:03 +03:00
//loading id to projectile mapping
2008-11-01 00:41:22 +02:00
tlog5 < < " \t \t Reading config/cr_shots.txt " < < std : : endl ;
2009-10-04 05:02:45 +03:00
std : : ifstream inp2 ( DATA_DIR " /config/cr_shots.txt " , std : : ios : : in | std : : ios : : binary ) ; //this file is not in lod
2008-08-02 18:08:03 +03:00
char dump [ 200 ] ;
inp2 . getline ( dump , 200 ) ;
while ( true )
{
int id ;
std : : string name ;
bool spin ;
inp2 > > id ;
if ( id = = - 1 )
break ;
inp2 > > name ;
idToProjectile [ id ] = name ;
inp2 > > spin ;
idToProjectileSpin [ id ] = spin ;
}
inp2 . close ( ) ;
2009-09-05 17:10:26 +03:00
//reading factionToTurretCreature
tlog5 < < " \t \t Reading config/cr_to_turret.txt " < < std : : endl ;
2009-10-04 05:02:45 +03:00
std : : ifstream inp3 ( DATA_DIR " /config/cr_to_turret.txt " , std : : ios : : in | std : : ios : : binary ) ; //this file is not in lod
2009-09-05 17:10:26 +03:00
std : : string dump2 ;
inp3 > > dump2 > > dump2 ;
for ( int g = 0 ; g < F_NUMBER ; + + g )
{
inp3 > > factionToTurretCreature [ g ] ;
}
inp3 . close ( ) ;
2011-02-02 20:49:48 +02:00
//reading creature ability names
ifs . open ( DATA_DIR " /config/bonusnames.txt " ) ;
{
std : : string buf2 , buf3 , line ;
int i ;
std : : map < std : : string , int > : : const_iterator it ;
getline ( ifs , line ) ; //skip 1st line
while ( ! ifs . eof ( ) )
{
getline ( ifs , buf , ' \t ' ) ;
getline ( ifs , buf2 , ' \t ' ) ;
getline ( ifs , buf3 ) ;
it = bonusNameMap . find ( buf ) ;
if ( it ! = bonusNameMap . end ( ) )
stackBonuses [ it - > second ] = std : : pair < std : : string , std : : string > ( buf2 , buf3 ) ;
else
tlog2 < < " Bonus " < < buf < < " not recognized, ingoring \n " ;
}
}
ifs . close ( ) ;
2011-02-03 14:58:46 +02:00
if ( STACK_EXP ) //reading default stack experience bonuses
{
buf = bitmaph - > getTextFile ( " CREXPBON.TXT " ) ;
2011-02-06 10:32:05 +02:00
int it = 0 ;
si32 creid = - 1 ;
2011-02-03 14:58:46 +02:00
commonBonuses . resize ( 8 ) ; //8 tiers
stackExperience b ;
b . expBonuses . resize ( 10 ) ;
b . source = Bonus : : STACK_EXPERIENCE ;
loadToIt ( dump2 , buf , it , 3 ) ; //ignore first line
loadToIt ( dump2 , buf , it , 4 ) ; //ignore index
loadStackExp ( b , buf , it ) ;
loadToIt ( dump2 , buf , it , 4 ) ; //crop comment
for ( i = 0 ; i < 8 ; + + i )
{
2011-02-06 10:32:05 +02:00
commonBonuses [ i ] . push_back ( new stackExperience ( b ) ) ; //health bonus common for all
2011-02-03 14:58:46 +02:00
for ( int j = 0 ; j < 4 ; + + j ) //four modifiers common for tiers
{
loadToIt ( dump2 , buf , it , 4 ) ; //ignore index
loadStackExp ( b , buf , it ) ;
2011-02-06 10:32:05 +02:00
commonBonuses [ i ] . push_back ( new stackExperience ( b ) ) ;
2011-02-03 14:58:46 +02:00
loadToIt ( dump2 , buf , it , 3 ) ; //crop comment
}
}
do //parse everything that's left
{
loadToIt ( creid , buf , it , 4 ) ; //get index
loadStackExp ( b , buf , it ) ;
2011-02-06 10:32:05 +02:00
creatures [ creid ] - > bonuses . push_back ( new stackExperience ( b ) ) ; //experience list is common for creatures of that type
2011-02-03 14:58:46 +02:00
loadToIt ( dump2 , buf , it , 3 ) ; //crop comment
2011-02-06 10:32:05 +02:00
} while ( it < buf . size ( ) ) ;
BOOST_FOREACH ( CCreature * c , creatures )
{
if ( it = c - > level < 7 )
std : : copy ( commonBonuses [ it - 1 ] . begin ( ) , commonBonuses [ it - 1 ] . end ( ) , c - > bonuses . begin ( ) ) ;
else
std : : copy ( commonBonuses [ 7 ] . begin ( ) , commonBonuses [ 7 ] . end ( ) , c - > bonuses . begin ( ) ) ; //common for tiers 8+
}
2011-02-03 14:58:46 +02:00
} //end of stack experience
2007-10-15 23:59:17 +03:00
}
void CCreatureHandler : : loadAnimationInfo ( )
{
2008-06-12 09:45:51 +03:00
std : : string buf = bitmaph - > getTextFile ( " CRANIM.TXT " ) ;
2008-03-05 19:01:41 +02:00
int andame = buf . size ( ) ;
int i = 0 ; //buf iterator
int hmcr = 0 ;
2010-10-25 22:37:21 +03:00
for ( ; i < andame ; + + i )
2008-03-05 19:01:41 +02:00
{
if ( buf [ i ] = = ' \r ' )
+ + hmcr ;
if ( hmcr = = 2 )
break ;
}
i + = 2 ;
2008-11-01 00:41:22 +02:00
for ( int dd = 0 ; dd < creatures . size ( ) ; + + dd )
2008-03-05 19:01:41 +02:00
{
2008-11-01 00:41:22 +02:00
//tlog5 << "\t\t\tReading animation info for creature " << dd << std::endl;
2010-05-02 21:20:26 +03:00
loadUnitAnimInfo ( * creatures [ dd ] , buf , i ) ;
2008-03-05 19:01:41 +02:00
}
2007-06-18 13:49:06 +03:00
return ;
}
void CCreatureHandler : : loadUnitAnimInfo ( CCreature & unit , std : : string & src , int & i )
{
int befi = i ;
2009-06-28 17:57:00 +03:00
unit . timeBetweenFidgets = readFloat ( befi , i , src . size ( ) , src ) ;
2007-06-18 13:49:06 +03:00
while ( unit . timeBetweenFidgets = = 0.0 )
{
2010-10-25 22:37:21 +03:00
for ( ; i < src . size ( ) ; + + i )
2007-06-18 13:49:06 +03:00
{
if ( src [ i ] = = ' \r ' )
break ;
}
i + = 2 ;
2009-06-28 17:57:00 +03:00
unit . timeBetweenFidgets = readFloat ( befi , i , src . size ( ) , src ) ;
2007-06-18 13:49:06 +03:00
}
2009-06-28 17:57:00 +03:00
unit . walkAnimationTime = readFloat ( befi , i , src . size ( ) , src ) ;
unit . attackAnimationTime = readFloat ( befi , i , src . size ( ) , src ) ;
unit . flightAnimationDistance = readFloat ( befi , i , src . size ( ) , src ) ;
2007-06-18 13:49:06 +03:00
///////////////////////
2009-06-28 17:57:00 +03:00
unit . upperRightMissleOffsetX = readNumber ( befi , i , src . size ( ) , src ) ;
unit . upperRightMissleOffsetY = readNumber ( befi , i , src . size ( ) , src ) ;
unit . rightMissleOffsetX = readNumber ( befi , i , src . size ( ) , src ) ;
unit . rightMissleOffsetY = readNumber ( befi , i , src . size ( ) , src ) ;
unit . lowerRightMissleOffsetX = readNumber ( befi , i , src . size ( ) , src ) ;
unit . lowerRightMissleOffsetY = readNumber ( befi , i , src . size ( ) , src ) ;
2007-06-18 13:49:06 +03:00
///////////////////////
for ( int jjj = 0 ; jjj < 12 ; + + jjj )
{
2009-06-28 17:57:00 +03:00
unit . missleFrameAngles [ jjj ] = readFloat ( befi , i , src . size ( ) , src ) ;
2007-06-18 13:49:06 +03:00
}
2009-06-28 17:57:00 +03:00
unit . troopCountLocationOffset = readNumber ( befi , i , src . size ( ) , src ) ;
unit . attackClimaxFrame = readNumber ( befi , i , src . size ( ) , src ) ;
2007-06-18 13:49:06 +03:00
2010-10-25 22:37:21 +03:00
for ( ; i < src . size ( ) ; + + i )
2007-06-18 13:49:06 +03:00
{
if ( src [ i ] = = ' \r ' )
break ;
}
i + = 2 ;
2008-08-02 18:08:03 +03:00
}
2009-01-11 00:08:18 +02:00
2011-02-03 14:58:46 +02:00
void CCreatureHandler : : loadStackExp ( stackExperience & b , std : : string & src , int & it ) //help function for parsing CREXPBON.txt, assuming all its details are already defined
{
std : : string buf , mod ;
loadToIt ( buf , src , it , 4 ) ;
loadToIt ( mod , src , it , 4 ) ;
switch ( buf [ 0 ] )
{
2011-02-06 10:32:05 +02:00
case ' H ' :
b . type = Bonus : : STACK_HEALTH ;
break ;
case ' A ' :
b . type = Bonus : : PRIMARY_SKILL ;
b . subtype = PrimarySkill : : ATTACK ;
break ;
case ' D ' :
b . type = Bonus : : PRIMARY_SKILL ;
b . subtype = PrimarySkill : : DEFENSE ;
break ;
case ' M ' : //Max damage
b . type = Bonus : : CREATURE_DAMAGE ;
b . subtype = 2 ;
break ;
case ' m ' : //Min damage
b . type = Bonus : : CREATURE_DAMAGE ;
b . subtype = 1 ;
break ;
2011-02-03 14:58:46 +02:00
}
loadToIt ( b . val , src , it , 4 ) ; //basic value, not particularly useful but existent
for ( int i = 0 ; i < 10 ; + + i )
{
loadToIt ( b . expBonuses [ i ] , src , it , 4 ) ; //vector must have length 10
}
}
2009-01-11 00:08:18 +02:00
CCreatureHandler : : ~ CCreatureHandler ( )
{
2009-05-24 01:57:39 +03:00
}
2010-07-24 00:05:49 +03:00
int CCreatureHandler : : pickRandomMonster ( const boost : : function < int ( ) > & randGen ) const
{
int r = 0 ;
do
{
if ( randGen )
r = randGen ( ) ;
else
r = rand ( ) ;
r % = 197 ;
} while ( vstd : : contains ( VLC - > creh - > notUsedMonsters , r ) ) ;
return r ;
}