1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00
vcmi/client/Graphics.cpp
Michał W. Urbańczyk 617e1f962e New files for lib:
* lib/ERMScriptModule.cpp
* lib/ERMScriptModule.h
* lib/CObstacleInstance.h

More jugglery with callbacks. Moving stuff from CGameState to CGameInfoCallback. Work on unified game events interface for player (AI or GUI) and script module. Directing events to ERM interpretetr, first attempts of calling some triggers. Crashy, if there any scripts.
Some other changes, including fighting amount of includes in includes and tracking of hero visits (need further work).
2011-05-09 22:20:47 +00:00

822 lines
23 KiB
C++

#include "../stdafx.h"
#include "Graphics.h"
#include "CDefHandler.h"
#include "SDL_Extensions.h"
#include <SDL_ttf.h>
#include <boost/assign/std/vector.hpp>
#include <sstream>
#include <iomanip>
#include <boost/thread.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/assign/std/vector.hpp>
#include "../CThreadHelper.h"
#include "CGameInfo.h"
#include "../lib/CLodHandler.h"
#include "../lib/VCMI_Lib.h"
#include "../CCallback.h"
#include "../lib/CTownHandler.h"
#include "../lib/CObjectHandler.h"
#include "../lib/CGeneralTextHandler.h"
#include "../lib/CCreatureHandler.h"
#include "CBitmapHandler.h"
#include "../lib/CObjectHandler.h"
#include "../lib/CDefObjInfoHandler.h"
#include "../lib/CGameState.h"
using namespace boost::assign;
using namespace CSDL_Ext;
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
/*
* Graphics.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
*
*/
Graphics * graphics = NULL;
SDL_Surface * Graphics::drawHeroInfoWin(const InfoAboutHero &curh)
{
char buf[15];
blueToPlayersAdv(hInfo,curh.owner);
SDL_Surface * ret = SDL_DisplayFormat(hInfo);
SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,0,255,255));
printAt(curh.name,75,13,FONT_SMALL,zwykly,ret); //name
blitAt(graphics->portraitLarge[curh.portrait],11,12,ret); //portrait
//army
for (ArmyDescriptor::const_iterator i = curh.army.begin(); i!=curh.army.end();i++)
{
blitAt(graphics->smallImgs[i->second.type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
if(curh.details)
{
SDL_itoa((*i).second.count,buf,10);
printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
}
else
{
printAtMiddle(VLC->generaltexth->arraytxt[174 + 3*(i->second.count)],slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
}
}
if(curh.details)
{
for (int i = 0; i < PRIMARY_SKILLS; i++)
{
SDL_itoa(curh.details->primskills[i], buf, 10);
printAtMiddle(buf,84+28*i,70,FONT_SMALL,zwykly,ret);
}
//mana points
SDL_itoa(curh.details->mana,buf,10);
printAtMiddle(buf,167,108,FONT_TINY,zwykly,ret);
blitAt(morale22->ourImages[curh.details->morale+3].bitmap,14,84,ret); //luck
blitAt(luck22->ourImages[curh.details->morale+3].bitmap,14,101,ret); //morale
}
return ret;
}
SDL_Surface * Graphics::drawHeroInfoWin(const CGHeroInstance * curh)
{
InfoAboutHero iah;
iah.initFromHero(curh, true);
return drawHeroInfoWin(iah);
}
SDL_Surface * Graphics::drawTownInfoWin(const CGTownInstance * curh)
{
InfoAboutTown iah;
iah.initFromTown(curh, true);
return drawTownInfoWin(iah);
}
SDL_Surface * Graphics::drawTownInfoWin( const InfoAboutTown & curh )
{
char buf[10];
blueToPlayersAdv(tInfo,curh.owner);
SDL_Surface * ret = SDL_DisplayFormat(tInfo);
SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,0,255,255));
printAt(curh.name,75,12,FONT_SMALL,zwykly,ret); //name
int pom = curh.fortLevel - 1; if(pom<0) pom = 3; //fort pic id
blitAt(forts->ourImages[pom].bitmap,115,42,ret); //fort
for (ArmyDescriptor::const_iterator i=curh.army.begin(); i!=curh.army.end();i++)
{
//if(!i->second.second)
// continue;
blitAt(graphics->smallImgs[(*i).second.type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
if(curh.details)
{
// Show exact creature amount.
SDL_itoa((*i).second.count,buf,10);
printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
}
else
{
// Show only a rough amount for creature stacks.
// TODO: Deal with case when no information at all about size shold be presented.
std::string roughAmount = curh.obj->getRoughAmount(i->first);
printAtMiddle(roughAmount,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
}
}
//blit town icon
if (curh.tType) {
pom = curh.tType->typeID*2;
if (!curh.fortLevel)
pom += F_NUMBER*2;
if(curh.built)
pom++;
blitAt(bigTownPic->ourImages[pom].bitmap,13,13,ret);
}
if(curh.details)
{
//hall level icon
if((pom=curh.details->hallLevel) >= 0)
blitAt(halls->ourImages[pom].bitmap, 77, 42, ret);
if (curh.details->goldIncome >= 0) {
SDL_itoa(curh.details->goldIncome, buf, 10); //gold income
printAtMiddle(buf, 167, 70, FONT_TINY, zwykly, ret);
}
if(curh.details->garrisonedHero) //garrisoned hero icon
blitAt(graphics->heroInGarrison,158,87,ret);
}
return ret;
}
void Graphics::loadPaletteAndColors()
{
std::string pals = bitmaph->getTextFile("PLAYERS.PAL", FILE_OTHER);
playerColorPalette = new SDL_Color[256];
neutralColor = new SDL_Color;
playerColors = new SDL_Color[PLAYER_LIMIT];
int startPoint = 24; //beginning byte; used to read
for(int i=0; i<256; ++i)
{
SDL_Color col;
col.r = pals[startPoint++];
col.g = pals[startPoint++];
col.b = pals[startPoint++];
col.unused = pals[startPoint++];
playerColorPalette[i] = col;
}
neutralColorPalette = new SDL_Color[32];
std::ifstream ncp;
ncp.open(DATA_DIR "/config/NEUTRAL.PAL", std::ios::binary);
for(int i=0; i<32; ++i)
{
ncp.read((char*)&neutralColorPalette[i].r,1);
ncp.read((char*)&neutralColorPalette[i].g,1);
ncp.read((char*)&neutralColorPalette[i].b,1);
ncp.read((char*)&neutralColorPalette[i].unused,1);
}
//colors initialization
int3 kolory[] = {int3(0xff,0,0),int3(0x31,0x52,0xff),int3(0x9c,0x73,0x52),int3(0x42,0x94,0x29),
int3(0xff,0x84,0x0),int3(0x8c,0x29,0xa5),int3(0x09,0x9c,0xa5),int3(0xc6,0x7b,0x8c)};
for(int i=0;i<8;i++)
{
playerColors[i].r = kolory[i].x;
playerColors[i].g = kolory[i].y;
playerColors[i].b = kolory[i].z;
playerColors[i].unused = 0;
}
neutralColor->r = 0x84; neutralColor->g = 0x84; neutralColor->b = 0x84; neutralColor->unused = 0x0;//gray
std::ifstream tpics(DATA_DIR "/config/townPics.txt");
assert(tpics.is_open());
while(!tpics.eof())
{
tpics >> pals;
townBgs.push_back(pals);
tpics >> pals;
guildBgs.push_back(pals);
tpics >> pals;
buildingPics.push_back(pals);
}
tpics.close();
}
void Graphics::initializeBattleGraphics()
{
std::ifstream bback(DATA_DIR "/config/battleBack.txt");
battleBacks.resize(26);
for(int i=1; i<26; ++i) //25 - number of terrains battle can be fought on
{
int am;
bback>>am;
battleBacks[i].resize(am);
for(int f=0; f<am; ++f)
{
bback>>battleBacks[i][f];
}
}
//initializing battle hero animation
std::ifstream bher(DATA_DIR "/config/battleHeroes.txt");
int numberofh;
bher>>numberofh;
battleHeroes.resize(numberofh);
for(int i=0; i<numberofh; ++i) //9 - number of terrains battle can be fought on
{
bher>>battleHeroes[i];
}
//initialization of AC->def name mapping
std::ifstream acd;
acd.open(DATA_DIR "/config/AC_desc.txt", std::ios::binary);
if(!acd.is_open())
{
tlog1<<"lack of config/AC_desc.txt file!"<<std::endl;
}
else
{
std::string buf;
acd>>buf;
int ACid, numberOfDefs;
while(true)
{
std::vector< std::string > toAdd;
acd>>ACid;
if(ACid == -1)
break;
acd>>numberOfDefs;
for(int g=0; g<numberOfDefs; ++g)
{
acd>>buf;
toAdd.push_back(buf);
}
battleACToDef[ACid] = toAdd;
}
}
spellEffectsPics = CDefHandler::giveDefEss("SpellInt.def");
}
Graphics::Graphics()
{
slotsPos.push_back(std::pair<int,int>(44,82));
slotsPos.push_back(std::pair<int,int>(80,82));
slotsPos.push_back(std::pair<int,int>(116,82));
slotsPos.push_back(std::pair<int,int>(26,131));
slotsPos.push_back(std::pair<int,int>(62,131));
slotsPos.push_back(std::pair<int,int>(98,131));
slotsPos.push_back(std::pair<int,int>(134,131));
CDefHandler *smi, *smi2;
std::vector<Task> tasks; //preparing list of graphics to load
tasks += boost::bind(&Graphics::loadFonts,this);
tasks += boost::bind(&Graphics::loadTrueType,this);
tasks += boost::bind(&Graphics::loadPaletteAndColors,this);
tasks += boost::bind(&Graphics::loadHeroFlags,this);
tasks += boost::bind(&Graphics::loadHeroPortraits,this);
tasks += boost::bind(&Graphics::initializeBattleGraphics,this);
tasks += boost::bind(&Graphics::loadWallPositions,this);
tasks += boost::bind(&Graphics::loadErmuToPicture,this);
tasks += GET_SURFACE(hInfo,"HEROQVBK.bmp");
tasks += GET_SURFACE(tInfo,"TOWNQVBK.bmp");
tasks += GET_SURFACE(heroInGarrison,"TOWNQKGH.bmp");
tasks += GET_DEF_ESS(artDefs,"ARTIFACT.DEF");
tasks += GET_DEF_ESS(forts,"ITMCLS.DEF");
tasks += GET_DEF_ESS(luck22,"ILCK22.DEF");
tasks += GET_DEF_ESS(luck30,"ILCK30.DEF");
tasks += GET_DEF_ESS(luck42,"ILCK42.DEF");
tasks += GET_DEF_ESS(luck82,"ILCK82.DEF");
tasks += GET_DEF_ESS(morale22,"IMRL22.DEF");
tasks += GET_DEF_ESS(morale30,"IMRL30.DEF");
tasks += GET_DEF_ESS(morale42,"IMRL42.DEF");
tasks += GET_DEF_ESS(morale82,"IMRL82.DEF");
tasks += GET_DEF_ESS(halls,"ITMTLS.DEF");
tasks += GET_DEF_ESS(bigTownPic,"ITPT.DEF");
tasks += GET_DEF_ESS(pskillsb,"PSKILL.DEF");
tasks += GET_DEF_ESS(pskillsm,"PSKIL42.DEF");
tasks += GET_DEF_ESS(pskillst,"PSKIL32.DEF");
tasks += GET_DEF_ESS(resources,"RESOUR82.DEF");
tasks += GET_DEF_ESS(un32,"UN32.DEF");
tasks += GET_DEF_ESS(un44,"UN44.DEF");
tasks += GET_DEF_ESS(smallIcons,"ITPA.DEF");
tasks += GET_DEF_ESS(resources32,"RESOURCE.DEF");
tasks += GET_DEF(smi,"CPRSMALL.DEF");
tasks += GET_DEF(smi2,"TWCRPORT.DEF");
tasks += GET_DEF_ESS(flags,"CREST58.DEF");
tasks += GET_DEF_ESS(abils32,"SECSK32.DEF");
tasks += GET_DEF_ESS(abils44,"SECSKILL.DEF");
tasks += GET_DEF_ESS(abils82,"SECSK82.DEF");
tasks += GET_DEF_ESS(spellscr,"SPELLSCR.DEF");
tasks += GET_DEF_ESS(heroMoveArrows,"ADAG.DEF");
std::ifstream ifs(DATA_DIR "/config/cr_bgs.txt");
int id;
std::string name;
while(!ifs.eof())
{
ifs >> id >> name;
tasks += GET_SURFACE(backgrounds[id],name);
name.replace(0,5,"TPCAS");
tasks += GET_SURFACE(backgroundsm[id],name);
}
CThreadHelper th(&tasks,std::max((unsigned int)1,boost::thread::hardware_concurrency()));
th.run();
for(size_t y=0; y < heroMoveArrows->ourImages.size(); ++y)
{
CSDL_Ext::alphaTransform(heroMoveArrows->ourImages[y].bitmap);
}
//handling 32x32px imgs
smi->notFreeImgs = true;
for (size_t i=0; i<smi->ourImages.size(); ++i)
{
smallImgs[i-2] = smi->ourImages[i].bitmap;
}
delete smi;
smi2->notFreeImgs = true;
for (size_t i=0; i<smi2->ourImages.size(); ++i)
{
bigImgs[i-2] = smi2->ourImages[i].bitmap;
}
delete smi2;
}
void Graphics::loadHeroPortraits()
{
std::ifstream of(DATA_DIR "/config/portrety.txt");
int numberOfPortraits;
of>>numberOfPortraits;
for (int j=0; j<numberOfPortraits; j++)
{
int ID;
of>>ID;
std::string path;
of>>path;
portraitSmall.push_back(BitmapHandler::loadBitmap(path));
for(size_t ff=0; ff<path.size(); ++ff) //size letter is usually third one, but there are exceptions an it should fix the problem
{
if(path[ff]=='S')
{
path[ff]='L';
break;
}
}
portraitLarge.push_back(BitmapHandler::loadBitmap(path));
SDL_SetColorKey(portraitLarge[portraitLarge.size()-1],SDL_SRCCOLORKEY,SDL_MapRGB(portraitLarge[portraitLarge.size()-1]->format,0,255,255));
}
of.close();
}
void Graphics::loadWallPositions()
{
std::ifstream inp;
inp.open(DATA_DIR "/config/wall_pos.txt", std::ios_base::in|std::ios_base::binary);
if(!inp.is_open())
{
tlog1<<"missing file: config/wall_pos.txt"<<std::endl;
}
else
{
const int MAX_BUF = 2000;
char buf[MAX_BUF+1];
// skip the first three lines because they are comment lines
inp.getline(buf, MAX_BUF);
inp.getline(buf, MAX_BUF);
inp.getline(buf, MAX_BUF);
std::string dump;
for(int g=0; g<ARRAY_COUNT(wallPositions); ++g)
{
inp >> dump;
for(int b = 0; b < 20; ++b)
{
Point pt;
inp >> pt.x;
inp >> pt.y;
wallPositions[g].push_back(pt);
}
}
}
inp.close();
}
void Graphics::loadHeroAnims()
{
std::vector<std::pair<int,int> > rotations; //first - group number to be rotated1, second - group number after rotation1
rotations += std::make_pair(6,10), std::make_pair(7,11), std::make_pair(8,12), std::make_pair(1,13),
std::make_pair(2,14), std::make_pair(3,15);
for(size_t i=0; i<F_NUMBER * 2; ++i)
{
std::ostringstream nm;
nm << "AH" << std::setw(2) << std::setfill('0') << i << "_.DEF";
loadHeroAnim(nm.str(), rotations, &Graphics::heroAnims);
std::string name = nm.str();
}
loadHeroAnim("AB01_.DEF", rotations, &Graphics::boatAnims);
loadHeroAnim("AB02_.DEF", rotations, &Graphics::boatAnims);
loadHeroAnim("AB03_.DEF", rotations, &Graphics::boatAnims);
}
void Graphics::loadHeroAnim( const std::string &name, const std::vector<std::pair<int,int> > &rotations, std::vector<CDefEssential *> Graphics::*dst )
{
CDefEssential *anim = CDefHandler::giveDefEss(name);
(this->*dst).push_back(anim);
int pom = 0; //how many groups has been rotated
for(int o=7; pom<6; ++o)
{
for(int p=0;p<6;p++)
{
if(anim->ourImages[o].groupNumber == rotations[p].first)
{
for(int e=0; e<8; ++e)
{
Cimage nci;
nci.bitmap = CSDL_Ext::rotate01(anim->ourImages[o+e].bitmap);
nci.groupNumber = rotations[p].second;
nci.imName = std::string();
anim->ourImages.push_back(nci);
if(pom>2) //we need only one frame for groups 13/14/15
break;
}
if(pom<3) //there are eight frames of animtion of groups 6/7/8 so for speed we'll skip them
o+=8;
else //there is only one frame of 1/2/3
o+=1;
++pom;
if(p==2 && pom<4) //group1 starts at index 1
o = 1;
}
}
}
for(size_t ff=0; ff<anim->ourImages.size(); ++ff)
{
CSDL_Ext::alphaTransform(anim->ourImages[ff].bitmap);
}
}
void Graphics::loadHeroFlags(std::pair<std::vector<CDefEssential *> Graphics::*, std::vector<const char *> > &pr, bool mode)
{
for(int i=0;i<8;i++)
(this->*pr.first).push_back(CDefHandler::giveDefEss(pr.second[i]));
std::vector<std::pair<int,int> > rotations; //first - group number to be rotated1, second - group number after rotation1
rotations += std::make_pair(6,10), std::make_pair(7,11), std::make_pair(8,12);
for(int q=0; q<8; ++q)
{
std::vector<Cimage> &curImgs = (this->*pr.first)[q]->ourImages;
for(size_t o=0; o<curImgs.size(); ++o)
{
for(size_t p=0; p<rotations.size(); p++)
{
if(curImgs[o].groupNumber==rotations[p].first)
{
for(int e=0; e<8; ++e)
{
Cimage nci;
nci.bitmap = CSDL_Ext::rotate01(curImgs[o+e].bitmap);
nci.groupNumber = rotations[p].second;
nci.imName = std::string();
curImgs.push_back(nci);
}
o+=8;
}
}
}
if (mode)
{
for(size_t o=0; o<curImgs.size(); ++o)
{
if(curImgs[o].groupNumber==1 || curImgs[o].groupNumber==2 || curImgs[o].groupNumber==3)
{
for(int e=0; e<8; ++e)
{
Cimage nci;
nci.bitmap = CSDL_Ext::rotate01(curImgs[o+e].bitmap);
nci.groupNumber = 12 + curImgs[o].groupNumber;
nci.imName = std::string();
curImgs.push_back(nci);
}
o+=8;
}
}
}
for(size_t ff=0; ff<curImgs.size(); ++ff)
{
SDL_SetColorKey(curImgs[ff].bitmap, SDL_SRCCOLORKEY,
SDL_MapRGB(curImgs[ff].bitmap->format, 0, 255, 255)
);
}
}
}
void Graphics::loadHeroFlags()
{
using namespace boost::assign;
timeHandler th;
std::pair<std::vector<CDefEssential *> Graphics::*, std::vector<const char *> > pr[4];
pr[0].first = &Graphics::flags1;
pr[0].second+=("ABF01L.DEF"),("ABF01G.DEF"),("ABF01R.DEF"),("ABF01D.DEF"),("ABF01B.DEF"),
("ABF01P.DEF"),("ABF01W.DEF"),("ABF01K.DEF");
pr[1].first = &Graphics::flags2;
pr[1].second+=("ABF02L.DEF"),("ABF02G.DEF"),("ABF02R.DEF"),("ABF02D.DEF"),("ABF02B.DEF"),
("ABF02P.DEF"),("ABF02W.DEF"),("ABF02K.DEF");
pr[2].first = &Graphics::flags3;
pr[2].second+=("ABF03L.DEF"),("ABF03G.DEF"),("ABF03R.DEF"),("ABF03D.DEF"),("ABF03B.DEF"),
("ABF03P.DEF"),("ABF03W.DEF"),("ABF03K.DEF");
pr[3].first = &Graphics::flags4;
pr[3].second+=("AF00.DEF"),("AF01.DEF"),("AF02.DEF"),("AF03.DEF"),("AF04.DEF"),
("AF05.DEF"),("AF06.DEF"),("AF07.DEF");
boost::thread_group grupa;
for(int g=3; g>=0; --g)
{
grupa.create_thread(boost::bind(&Graphics::loadHeroFlags,this,boost::ref(pr[g]),true));
}
grupa.join_all();
tlog0 << "Loading and transforming heroes' flags: "<<th.getDif()<<std::endl;
}
SDL_Surface * Graphics::getPic(int ID, bool fort, bool builded)
{
if (ID==-1)
return smallIcons->ourImages[0].bitmap;
else if (ID==-2)
return smallIcons->ourImages[1].bitmap;
else if (ID==-3)
return smallIcons->ourImages[2+F_NUMBER*4].bitmap;
else if (ID>F_NUMBER || ID<-3)
#ifndef __GNUC__
throw new std::exception("Invalid ID");
#else
throw new std::exception();
#endif
else
{
int pom = 3;
if(!fort)
pom+=F_NUMBER*2;
pom += ID*2;
if (!builded)
pom--;
return smallIcons->ourImages[pom].bitmap;
}
}
void Graphics::blueToPlayersAdv(SDL_Surface * sur, int player)
{
// if(player==1) //it is actually blue...
// return;
if(sur->format->BitsPerPixel == 8)
{
SDL_Color *palette = NULL;
if(player < PLAYER_LIMIT && player >= 0)
{
palette = playerColorPalette + 32*player;
}
else if(player == 255 || player == -1)
{
palette = neutralColorPalette;
}
else
{
tlog1 << "Wrong player id in blueToPlayersAdv (" << player << ")!\n";
return;
}
SDL_SetColors(sur, palette, 224, 32);
//for(int i=0; i<32; ++i)
//{
// sur->format->palette->colors[224+i] = palette[i];
//}
}
else if(sur->format->BitsPerPixel == 24) //should never happen in general
{
for(int y=0; y<sur->h; ++y)
{
for(int x=0; x<sur->w; ++x)
{
Uint8* cp = (Uint8*)sur->pixels + y*sur->pitch + x*3;
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
if(cp[2]>cp[1] && cp[2]>cp[0])
{
std::vector<long long int> sort1;
sort1.push_back(cp[0]);
sort1.push_back(cp[1]);
sort1.push_back(cp[2]);
std::vector< std::pair<long long int, Uint8*> > sort2;
sort2.push_back(std::make_pair(graphics->playerColors[player].r, &(cp[0])));
sort2.push_back(std::make_pair(graphics->playerColors[player].g, &(cp[1])));
sort2.push_back(std::make_pair(graphics->playerColors[player].b, &(cp[2])));
std::sort(sort1.begin(), sort1.end());
if(sort2[0].first>sort2[1].first)
std::swap(sort2[0], sort2[1]);
if(sort2[1].first>sort2[2].first)
std::swap(sort2[1], sort2[2]);
if(sort2[0].first>sort2[1].first)
std::swap(sort2[0], sort2[1]);
for(int hh=0; hh<3; ++hh)
{
(*sort2[hh].second) = (sort1[hh] + sort2[hh].first)/2.2;
}
}
}
else
{
if(
(/*(mode==0) && (cp[0]>cp[1]) && (cp[0]>cp[2])) ||
((mode==1) &&*/ (cp[2]<45) && (cp[0]>80) && (cp[1]<70) && ((cp[0]-cp[1])>40))
)
{
std::vector<long long int> sort1;
sort1.push_back(cp[2]);
sort1.push_back(cp[1]);
sort1.push_back(cp[0]);
std::vector< std::pair<long long int, Uint8*> > sort2;
sort2.push_back(std::make_pair(graphics->playerColors[player].r, &(cp[2])));
sort2.push_back(std::make_pair(graphics->playerColors[player].g, &(cp[1])));
sort2.push_back(std::make_pair(graphics->playerColors[player].b, &(cp[0])));
std::sort(sort1.begin(), sort1.end());
if(sort2[0].first>sort2[1].first)
std::swap(sort2[0], sort2[1]);
if(sort2[1].first>sort2[2].first)
std::swap(sort2[1], sort2[2]);
if(sort2[0].first>sort2[1].first)
std::swap(sort2[0], sort2[1]);
for(int hh=0; hh<3; ++hh)
{
(*sort2[hh].second) = (sort1[hh]*0.8 + sort2[hh].first)/2;
}
}
}
}
}
}
}
void Graphics::loadTrueType()
{
bool ttfPresent = false;//was TTF initialised or not
for(int i = 0; i < FONTS_NUMBER; i++)
fontsTrueType[i] = NULL;
std::ifstream ff(DATA_DIR "/config/fonts.txt");
while(!ff.eof())
{
int enabl, fntID, fntSize;
std::string fntName;
ff >> enabl;//enabled font or not
if (enabl==-1)
break;//end of data
ff >> fntID;//what font will be replaced
ff >> fntName;//name of truetype font
ff >> fntSize;//size of font
if (enabl)
{
if (!ttfPresent)
{
ttfPresent = true;
TTF_Init();
atexit(TTF_Quit);
};
fntName = DATA_DIR + ( "/Fonts/" + fntName);
fontsTrueType[fntID] = TTF_OpenFont(fntName.c_str(),fntSize);
}
}
ff.close();
ff.clear();
}
Font * Graphics::loadFont( const char * name )
{
int len = 0;
unsigned char * hlp = bitmaph->giveFile(name, FILE_FONT, &len);
if(!hlp || !len)
{
tlog1 << "Error: cannot load font: " << name << std::endl;
return NULL;
}
int magic = *(const int*)hlp;
if(len < 10000 || (magic != 589598 && magic != 589599))
{
tlog1 << "Suspicious font file (length " << len <<", fname " << name << "), logging to suspicious_" << name << ".fnt\n";
std::string suspFName = "suspicious_" + std::string(name) + ".fnt";
std::ofstream o(suspFName.c_str());
o.write((const char*)hlp, len);
}
Font *ret = new Font(hlp);
return ret;
}
void Graphics::loadFonts()
{
static const char *fontnames [] = {"BIGFONT.FNT", "CALLI10R.FNT", "CREDITS.FNT", "HISCORE.FNT", "MEDFONT.FNT",
"SMALFONT.FNT", "TIMES08R.FNT", "TINY.FNT", "VERD10B.FNT"} ;
assert(ARRAY_COUNT(fontnames) == FONTS_NUMBER);
for(int i = 0; i < FONTS_NUMBER; i++)
fonts[i] = loadFont(fontnames[i]);
}
CDefEssential * Graphics::getDef( const CGObjectInstance * obj )
{
return advmapobjGraphics[obj->defInfo->id][obj->defInfo->subid];
}
CDefEssential * Graphics::getDef( const CGDefInfo * info )
{
return advmapobjGraphics[info->id][info->subid];
}
void Graphics::loadErmuToPicture()
{
//loading ERMU to picture
std::ifstream etp(DATA_DIR "/config/ERMU_to_picture.txt");
assert(etp.is_open());
for(int g=0; g<44; ++g)
{
for (int b=0; b<ARRAY_COUNT(ERMUtoPicture); ++b)
{
std::string buf;
etp >> buf;
ERMUtoPicture[b][g] = buf;
}
}
etp.close();
}
Font::Font(unsigned char *Data)
{
data = Data;
int i = 0;
height = data[5];
i = 32;
for(int ci = 0; ci < 256; ci++)
{
chars[ci].unknown1 = readNormalNr(data, i); i+=4;
chars[ci].width = readNormalNr(data, i); i+=4;
chars[ci].unknown2 =readNormalNr(data, i); i+=4;
//if(ci>=30)
// tlog0 << ci << ". (" << (char)ci << "). Width: " << chars[ci].width << " U1/U2:" << chars[ci].unknown1 << "/" << chars[ci].unknown2 << std::endl;
}
for(int ci = 0; ci < 256; ci++)
{
chars[ci].offset = readNormalNr(data, i); i+=4;
chars[ci].pixels = data + 4128 + chars[ci].offset;
}
}
Font::~Font()
{
delete [] data;
}
int Font::getWidth(const char *text ) const
{
int length = std::strlen(text);
int ret = 0;
for(int i = 0; i < length; i++)
{
unsigned char c = text[i];
ret += chars[c].width + chars[c].unknown1 + chars[c].unknown2;
}
return ret;
}
int Font::getCharWidth( char c ) const
{
const Char &C = chars[(unsigned char)c];
return C.width + C.unknown1 + C.unknown2;;
}
/*
void Font::WriteAt(const char *text, SDL_Surface *sur, int x, int y )
{
SDL_Surface *SDL_CreateRGBSurfaceFrom(pixels, w, h, 8, int pitch,
224, 28, 3, 0);
}
*/