bugfix for scripted scenarios and placing unit model not showing

This commit is contained in:
Mark Vejvoda
2010-03-24 21:26:17 +00:00
parent eba5aa361c
commit b22adbfa02
18 changed files with 2381 additions and 147 deletions

482
source/glest_game/ai/ai.cpp Normal file
View File

@@ -0,0 +1,482 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "ai.h"
#include <ctime>
#include "ai_interface.h"
#include "ai_rule.h"
#include "unit_type.h"
#include "unit.h"
#include "program.h"
#include "config.h"
#include "leak_dumper.h"
using namespace Shared::Graphics;
using namespace Shared::Util;
namespace Glest{ namespace Game{
// =====================================================
// class ProduceTask
// =====================================================
ProduceTask::ProduceTask(UnitClass unitClass){
taskClass= tcProduce;
this->unitClass= unitClass;
unitType= NULL;
resourceType= NULL;
}
ProduceTask::ProduceTask(const UnitType *unitType){
taskClass= tcProduce;
this->unitType= unitType;
resourceType= NULL;
}
ProduceTask::ProduceTask(const ResourceType *resourceType){
taskClass= tcProduce;
unitType= NULL;
this->resourceType= resourceType;
}
string ProduceTask::toString() const{
string str= "Produce ";
if(unitType!=NULL){
str+= unitType->getName();
}
return str;
}
// =====================================================
// class BuildTask
// =====================================================
BuildTask::BuildTask(const UnitType *unitType){
taskClass= tcBuild;
this->unitType= unitType;
resourceType= NULL;
forcePos= false;
}
BuildTask::BuildTask(const ResourceType *resourceType){
taskClass= tcBuild;
unitType= NULL;
this->resourceType= resourceType;
forcePos= false;
}
BuildTask::BuildTask(const UnitType *unitType, const Vec2i &pos){
taskClass= tcBuild;
this->unitType= unitType;
resourceType= NULL;
forcePos= true;
this->pos= pos;
}
string BuildTask::toString() const{
string str= "Build ";
if(unitType!=NULL){
str+= unitType->getName();
}
return str;
}
// =====================================================
// class UpgradeTask
// =====================================================
UpgradeTask::UpgradeTask(const UpgradeType *upgradeType){
taskClass= tcUpgrade;
this->upgradeType= upgradeType;
}
string UpgradeTask::toString() const{
string str= "Build ";
if(upgradeType!=NULL){
str+= upgradeType->getName();
}
return str;
}
// =====================================================
// class Ai
// =====================================================
void Ai::init(AiInterface *aiInterface){
this->aiInterface= aiInterface;
startLoc= random.randRange(0, aiInterface->getMapMaxPlayers()-1);
upgradeCount= 0;
minWarriors= minMinWarriors;
randomMinWarriorsReached= false;
//add ai rules
aiRules.resize(14);
aiRules[0]= new AiRuleWorkerHarvest(this);
aiRules[1]= new AiRuleRefreshHarvester(this);
aiRules[2]= new AiRuleScoutPatrol(this);
aiRules[3]= new AiRuleReturnBase(this);
aiRules[4]= new AiRuleMassiveAttack(this);
aiRules[5]= new AiRuleAddTasks(this);
aiRules[6]= new AiRuleProduceResourceProducer(this);
aiRules[7]= new AiRuleBuildOneFarm(this);
aiRules[8]= new AiRuleProduce(this);
aiRules[9]= new AiRuleBuild(this);
aiRules[10]= new AiRuleUpgrade(this);
aiRules[11]= new AiRuleExpand(this);
aiRules[12]= new AiRuleRepair(this);
aiRules[13]= new AiRuleRepair(this);
}
Ai::~Ai(){
deleteValues(tasks.begin(), tasks.end());
deleteValues(aiRules.begin(), aiRules.end());
}
void Ai::update(){
//process ai rules
for(AiRules::iterator it= aiRules.begin(); it!=aiRules.end(); ++it){
if((aiInterface->getTimer() % ((*it)->getTestInterval()*GameConstants::updateFps/1000))==0){
if((*it)->test()){
aiInterface->printLog(3, intToStr(1000*aiInterface->getTimer()/GameConstants::updateFps) + ": Executing rule: " + (*it)->getName() + '\n');
(*it)->execute();
}
}
}
}
// ==================== state requests ====================
int Ai::getCountOfType(const UnitType *ut){
int count= 0;
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
if(ut == aiInterface->getMyUnit(i)->getType()){
count++;
}
}
return count;
}
int Ai::getCountOfClass(UnitClass uc){
int count= 0;
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
if(aiInterface->getMyUnit(i)->getType()->isOfClass(uc)){
++count;
}
}
return count;
}
float Ai::getRatioOfClass(UnitClass uc){
if(aiInterface->getMyUnitCount()==0){
return 0;
}
else{
return static_cast<float>(getCountOfClass(uc))/aiInterface->getMyUnitCount();
}
}
const ResourceType *Ai::getNeededResource(){
int amount= -1;
const ResourceType *neededResource= NULL;
const TechTree *tt= aiInterface->getTechTree();
for(int i=0; i<tt->getResourceTypeCount(); ++i){
const ResourceType *rt= tt->getResourceType(i);
const Resource *r= aiInterface->getResource(rt);
if(rt->getClass()!=rcStatic && rt->getClass()!=rcConsumable && (r->getAmount()<amount || amount==-1)){
amount= r->getAmount();
neededResource= rt;
}
}
return neededResource;
}
bool Ai::beingAttacked(Vec2i &pos, Field &field, int radius){
int count= aiInterface->onSightUnitCount();
const Unit *unit;
for(int i=0; i<count; ++i){
unit= aiInterface->getOnSightUnit(i);
if(!aiInterface->isAlly(unit) && unit->isAlive()){
pos= unit->getPos();
field= unit->getCurrField();
if(pos.dist(aiInterface->getHomeLocation())<radius){
aiInterface->printLog(2, "Being attacked at pos "+intToStr(pos.x)+","+intToStr(pos.y)+"\n");
return true;
}
}
}
return false;
}
bool Ai::isStableBase(){
if(getCountOfClass(ucWarrior)>minWarriors){
aiInterface->printLog(4, "Base is stable\n");
return true;
}
else{
aiInterface->printLog(4, "Base is not stable\n");
return false;
}
}
bool Ai::findAbleUnit(int *unitIndex, CommandClass ability, bool idleOnly){
vector<int> units;
*unitIndex= -1;
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
const Unit *unit= aiInterface->getMyUnit(i);
if(unit->getType()->hasCommandClass(ability)){
if(!idleOnly || !unit->anyCommand() || unit->getCurrCommand()->getCommandType()->getClass()==ccStop){
units.push_back(i);
}
}
}
if(units.empty()){
return false;
}
else{
*unitIndex= units[random.randRange(0, units.size()-1)];
return true;
}
}
bool Ai::findAbleUnit(int *unitIndex, CommandClass ability, CommandClass currentCommand){
vector<int> units;
*unitIndex= -1;
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
const Unit *unit= aiInterface->getMyUnit(i);
if(unit->getType()->hasCommandClass(ability)){
if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass()==currentCommand){
units.push_back(i);
}
}
}
if(units.empty()){
return false;
}
else{
*unitIndex= units[random.randRange(0, units.size()-1)];
return true;
}
}
bool Ai::findPosForBuilding(const UnitType* building, const Vec2i &searchPos, Vec2i &outPos){
const int spacing= 1;
for(int currRadius=0; currRadius<maxBuildRadius; ++currRadius){
for(int i=searchPos.x-currRadius; i<searchPos.x+currRadius; ++i){
for(int j=searchPos.y-currRadius; j<searchPos.y+currRadius; ++j){
outPos= Vec2i(i, j);
if(aiInterface->isFreeCells(outPos-Vec2i(spacing), building->getSize()+spacing*2, fLand)){
return true;
}
}
}
}
return false;
}
// ==================== tasks ====================
void Ai::addTask(const Task *task){
tasks.push_back(task);
aiInterface->printLog(2, "Task added: " + task->toString());
}
void Ai::addPriorityTask(const Task *task){
deleteValues(tasks.begin(), tasks.end());
tasks.clear();
tasks.push_back(task);
aiInterface->printLog(2, "Priority Task added: " + task->toString());
}
bool Ai::anyTask(){
return !tasks.empty();
}
const Task *Ai::getTask() const{
if(tasks.empty()){
return NULL;
}
else{
return tasks.front();
}
}
void Ai::removeTask(const Task *task){
aiInterface->printLog(2, "Task removed: " + task->toString());
tasks.remove(task);
delete task;
}
void Ai::retryTask(const Task *task){
tasks.remove(task);
tasks.push_back(task);
}
// ==================== expansions ====================
void Ai::addExpansion(const Vec2i &pos){
//check if there is a nearby expansion
for(Positions::iterator it= expansionPositions.begin(); it!=expansionPositions.end(); ++it){
if((*it).dist(pos)<villageRadius){
return;
}
}
//add expansion
expansionPositions.push_front(pos);
//remove expansion if queue is list is full
if(expansionPositions.size()>maxExpansions){
expansionPositions.pop_back();
}
}
Vec2i Ai::getRandomHomePosition(){
if(expansionPositions.empty() || random.randRange(0, 1) == 0){
return aiInterface->getHomeLocation();
}
return expansionPositions[random.randRange(0, expansionPositions.size()-1)];
}
// ==================== actions ====================
void Ai::sendScoutPatrol(){
Vec2i pos;
int unit;
startLoc= (startLoc+1) % aiInterface->getMapMaxPlayers();
pos= aiInterface->getStartLocation(startLoc);
if(aiInterface->getFactionIndex()!=startLoc){
if(findAbleUnit(&unit, ccAttack, false)){
aiInterface->giveCommand(unit, ccAttack, pos);
aiInterface->printLog(2, "Scout patrol sent to: " + intToStr(pos.x)+","+intToStr(pos.y)+"\n");
}
}
}
void Ai::massiveAttack(const Vec2i &pos, Field field, bool ultraAttack){
int producerWarriorCount=0;
int maxProducerWarriors=random.randRange(1,11);
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
bool isWarrior;
const Unit *unit= aiInterface->getMyUnit(i);
const AttackCommandType *act= unit->getType()->getFirstAttackCommand(field);
if(act!=NULL && unit->getType()->hasCommandClass(ccProduce))
{
producerWarriorCount++;
}
if(aiInterface->getControlType()==ctCpuMega)
{
if(producerWarriorCount>maxProducerWarriors)
{
if(
unit->getCommandSize()>0 &&
unit->getCurrCommand()->getCommandType()!=NULL && (
unit->getCurrCommand()->getCommandType()->getClass()==ccBuild ||
unit->getCurrCommand()->getCommandType()->getClass()==ccMorph ||
unit->getCurrCommand()->getCommandType()->getClass()==ccProduce
)
)
{
isWarrior=false;
}
else
{
isWarrior=!unit->getType()->hasCommandClass(ccHarvest);
}
}
else
{
isWarrior= !unit->getType()->hasCommandClass(ccHarvest) && !unit->getType()->hasCommandClass(ccProduce);
}
}
else
{
isWarrior= !unit->getType()->hasCommandClass(ccHarvest) && !unit->getType()->hasCommandClass(ccProduce);
}
bool alreadyAttacking= unit->getCurrSkill()->getClass()==scAttack;
if(!alreadyAttacking && act!=NULL && (ultraAttack || isWarrior)){
aiInterface->giveCommand(i, act, pos);
}
}
if(aiInterface->getControlType()==ctCpuEasy)
{
minWarriors+= 1;
}
else if(aiInterface->getControlType()==ctCpuMega)
{
minWarriors+= 3;
if(minWarriors>maxMinWarriors-1 || randomMinWarriorsReached)
{
randomMinWarriorsReached=true;
minWarriors=random.randRange(maxMinWarriors-10, maxMinWarriors*2);
}
}
else if(minWarriors<maxMinWarriors){
minWarriors+= 3;
}
aiInterface->printLog(2, "Massive attack to pos: "+ intToStr(pos.x)+", "+intToStr(pos.y)+"\n");
}
void Ai::returnBase(int unitIndex){
Vec2i pos;
CommandResult r;
int fi;
fi= aiInterface->getFactionIndex();
pos= Vec2i(
random.randRange(-villageRadius, villageRadius), random.randRange(-villageRadius, villageRadius)) +
getRandomHomePosition();
r= aiInterface->giveCommand(unitIndex, ccMove, pos);
//aiInterface->printLog(1, "Order return to base pos:" + intToStr(pos.x)+", "+intToStr(pos.y)+": "+rrToStr(r)+"\n");
}
void Ai::harvest(int unitIndex){
const ResourceType *rt= getNeededResource();
if(rt!=NULL){
const HarvestCommandType *hct= aiInterface->getMyUnit(unitIndex)->getType()->getFirstHarvestCommand(rt);
Vec2i resPos;
if(hct!=NULL && aiInterface->getNearestSightedResource(rt, aiInterface->getHomeLocation(), resPos)){
resPos= resPos+Vec2i(random.randRange(-2, 2), random.randRange(-2, 2));
aiInterface->giveCommand(unitIndex, hct, resPos);
//aiInterface->printLog(4, "Order harvest pos:" + intToStr(resPos.x)+", "+intToStr(resPos.y)+": "+rrToStr(r)+"\n");
}
}
}
}}//end namespace

189
source/glest_game/ai/ai.h Normal file
View File

@@ -0,0 +1,189 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#ifndef _GLEST_GAME_AI_H_
#define _GLEST_GAME_AI_H_
#include <vector>
#include <list>
#include "world.h"
#include "commander.h"
#include "command.h"
#include "random.h"
using std::deque;
using std::vector;
using std::list;
using Shared::Util::Random;
namespace Glest{ namespace Game{
class AiInterface;
class AiRule;
// =====================================================
// class Task
//
/// An action that has to be performed by the IA
// =====================================================
enum TaskClass{
tcProduce,
tcBuild,
tcUpgrade
};
class Task{
protected:
TaskClass taskClass;
public:
virtual ~Task(){}
TaskClass getClass() const {return taskClass;}
virtual string toString() const= 0;
};
// ==================== ProduceTask ====================
class ProduceTask: public Task{
private:
UnitClass unitClass;
const UnitType *unitType;
const ResourceType *resourceType;
public:
ProduceTask(UnitClass unitClass);
ProduceTask(const UnitType *unitType);
ProduceTask(const ResourceType *resourceType);
UnitClass getUnitClass() const {return unitClass;}
const UnitType *getUnitType() const {return unitType;}
const ResourceType *getResourceType() const {return resourceType;}
virtual string toString() const;
};
// ==================== BuildTask ====================
class BuildTask: public Task{
private:
const UnitType *unitType;
const ResourceType *resourceType;
bool forcePos;
Vec2i pos;
public:
BuildTask(const UnitType *unitType= NULL);
BuildTask(const ResourceType *resourceType);
BuildTask(const UnitType *unitType, const Vec2i &pos);
const UnitType *getUnitType() const {return unitType;}
const ResourceType *getResourceType() const {return resourceType;}
bool getForcePos() const {return forcePos;}
Vec2i getPos() const {return pos;}
virtual string toString() const;
};
// ==================== UpgradeTask ====================
class UpgradeTask: public Task{
private:
const UpgradeType *upgradeType;
public:
UpgradeTask(const UpgradeType *upgradeType= NULL);
const UpgradeType *getUpgradeType() const {return upgradeType;}
virtual string toString() const;
};
// ===============================
// class AI
//
/// Main AI class
// ===============================
class Ai{
private:
static const int harvesterPercent= 30;
static const int maxBuildRadius= 40;
static const int minMinWarriors= 7;
static const int maxMinWarriors= 20;
static const int minStaticResources= 10;
static const int minConsumableResources= 20;
static const int maxExpansions= 2;
static const int villageRadius= 15;
public:
enum ResourceUsage{
ruHarvester,
ruWarrior,
ruBuilding,
ruUpgrade
};
private:
typedef vector<AiRule*> AiRules;
typedef list<const Task*> Tasks;
typedef deque<Vec2i> Positions;
private:
AiInterface *aiInterface;
AiRules aiRules;
int startLoc;
bool randomMinWarriorsReached;
int upgradeCount;
Tasks tasks;
Positions expansionPositions;
Random random;
public:
int minWarriors;
~Ai();
void init(AiInterface *aiInterface);
void update();
//state requests
AiInterface *getAiInterface() const {return aiInterface;}
Random* getRandom() {return &random;}
int getCountOfType(const UnitType *ut);
int getCountOfClass(UnitClass uc);
float getRatioOfClass(UnitClass uc);
const ResourceType *getNeededResource();
bool isStableBase();
bool findPosForBuilding(const UnitType* building, const Vec2i &searchPos, Vec2i &pos);
bool findAbleUnit(int *unitIndex, CommandClass ability, bool idleOnly);
bool findAbleUnit(int *unitIndex, CommandClass ability, CommandClass currentCommand);
bool beingAttacked(Vec2i &pos, Field &field, int radius);
//tasks
void addTask(const Task *task);
void addPriorityTask(const Task *task);
bool anyTask();
const Task *getTask() const;
void removeTask(const Task *task);
void retryTask(const Task *task);
//expansions
void addExpansion(const Vec2i &pos);
Vec2i getRandomHomePosition();
//actions
void sendScoutPatrol();
void massiveAttack(const Vec2i &pos, Field field, bool ultraAttack= false);
void returnBase(int unitIndex);
void harvest(int unitIndex);
};
}}//end namespace
#endif

View File

@@ -0,0 +1,238 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "ai_interface.h"
#include "ai.h"
#include "command_type.h"
#include "faction.h"
#include "unit.h"
#include "unit_type.h"
#include "object.h"
#include "game.h"
#include "config.h"
#include "leak_dumper.h"
using namespace Shared::Util;
using namespace Shared::Graphics;
// =====================================================
// class AiInterface
// =====================================================
namespace Glest{ namespace Game{
AiInterface::AiInterface(Game &game, int factionIndex, int teamIndex){
this->world= game.getWorld();
this->commander= game.getCommander();
this->console= game.getConsole();
this->factionIndex= factionIndex;
this->teamIndex= teamIndex;
timer= 0;
//init ai
ai.init(this);
//config
logLevel= Config::getInstance().getInt("AiLog");
redir= Config::getInstance().getBool("AiRedir");
//clear log file
if(logLevel>0){
FILE *f= fopen(getLogFilename().c_str(), "wt");
if(f==NULL){
throw runtime_error("Can't open file: "+getLogFilename());
}
fprintf(f, "%s", "Glest AI log file\n\n");
fclose(f);
}
}
// ==================== main ====================
void AiInterface::update(){
timer++;
ai.update();
}
// ==================== misc ====================
void AiInterface::printLog(int logLevel, const string &s){
if(this->logLevel>=logLevel){
string logString= "(" + intToStr(factionIndex) + ") " + s;
//print log to file
FILE *f= fopen(getLogFilename().c_str(), "at");
if(f==NULL){
throw runtime_error("Can't open file: "+getLogFilename());
}
fprintf(f, "%s\n", logString.c_str());
fclose(f);
//redirect to console
if(redir) {
console->addLine(logString);
}
}
}
// ==================== interaction ====================
CommandResult AiInterface::giveCommand(int unitIndex, CommandClass commandClass, const Vec2i &pos){
Command *c= new Command (world->getFaction(factionIndex)->getUnit(unitIndex)->getType()->getFirstCtOfClass(commandClass), pos);
return world->getFaction(factionIndex)->getUnit(unitIndex)->giveCommand(c);
}
CommandResult AiInterface::giveCommand(int unitIndex, const CommandType *commandType, const Vec2i &pos){
return world->getFaction(factionIndex)->getUnit(unitIndex)->giveCommand(new Command(commandType, pos));
}
CommandResult AiInterface::giveCommand(int unitIndex, const CommandType *commandType, const Vec2i &pos, const UnitType *ut){
return world->getFaction(factionIndex)->getUnit(unitIndex)->giveCommand(new Command(commandType, pos, ut));
}
CommandResult AiInterface::giveCommand(int unitIndex, const CommandType *commandType, Unit *u){
return world->getFaction(factionIndex)->getUnit(unitIndex)->giveCommand(new Command(commandType, u));
}
// ==================== get data ====================
int AiInterface::getMapMaxPlayers(){
return world->getMaxPlayers();
}
Vec2i AiInterface::getHomeLocation(){
return world->getMap()->getStartLocation(world->getFaction(factionIndex)->getStartLocationIndex());
}
Vec2i AiInterface::getStartLocation(int loactionIndex){
return world->getMap()->getStartLocation(loactionIndex);
}
int AiInterface::getFactionCount(){
return world->getFactionCount();
}
int AiInterface::getMyUnitCount() const{
return world->getFaction(factionIndex)->getUnitCount();
}
int AiInterface::getMyUpgradeCount() const{
return world->getFaction(factionIndex)->getUpgradeManager()->getUpgradeCount();
}
int AiInterface::onSightUnitCount(){
int count=0;
Map *map= world->getMap();
for(int i=0; i<world->getFactionCount(); ++i){
for(int j=0; j<world->getFaction(i)->getUnitCount(); ++j){
SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(world->getFaction(i)->getUnit(j)->getPos()));
if(sc->isVisible(teamIndex)){
count++;
}
}
}
return count;
}
const Resource *AiInterface::getResource(const ResourceType *rt){
return world->getFaction(factionIndex)->getResource(rt);
}
const Unit *AiInterface::getMyUnit(int unitIndex){
return world->getFaction(factionIndex)->getUnit(unitIndex);
}
const Unit *AiInterface::getOnSightUnit(int unitIndex){
int count=0;
Map *map= world->getMap();
for(int i=0; i<world->getFactionCount(); ++i){
for(int j=0; j<world->getFaction(i)->getUnitCount(); ++j){
Unit *u= world->getFaction(i)->getUnit(j);
if(map->getSurfaceCell(Map::toSurfCoords(u->getPos()))->isVisible(teamIndex)){
if(count==unitIndex){
return u;
}
else{
count ++;
}
}
}
}
return NULL;
}
const FactionType * AiInterface::getMyFactionType(){
return world->getFaction(factionIndex)->getType();
}
const ControlType AiInterface::getControlType(){
return world->getFaction(factionIndex)->getControlType();
}
const TechTree *AiInterface::getTechTree(){
return world->getTechTree();
}
bool AiInterface::getNearestSightedResource(const ResourceType *rt, const Vec2i &pos, Vec2i &resultPos){
float tmpDist;
float nearestDist= infinity;
bool anyResource= false;
const Map *map= world->getMap();
for(int i=0; i<map->getW(); ++i){
for(int j=0; j<map->getH(); ++j){
Vec2i surfPos= Map::toSurfCoords(Vec2i(i, j));
//if explored cell
if(map->getSurfaceCell(surfPos)->isExplored(teamIndex)){
Resource *r= map->getSurfaceCell(surfPos)->getResource();
//if resource cell
if(r!=NULL && r->getType()==rt){
tmpDist= pos.dist(Vec2i(i, j));
if(tmpDist<nearestDist){
anyResource= true;
nearestDist= tmpDist;
resultPos= Vec2i(i, j);
}
}
}
}
}
return anyResource;
}
bool AiInterface::isAlly(const Unit *unit) const{
return world->getFaction(factionIndex)->isAlly(unit->getFaction());
}
bool AiInterface::reqsOk(const RequirableType *rt){
return world->getFaction(factionIndex)->reqsOk(rt);
}
bool AiInterface::reqsOk(const CommandType *ct){
return world->getFaction(factionIndex)->reqsOk(ct);
}
bool AiInterface::checkCosts(const ProducibleType *pt){
return world->getFaction(factionIndex)->checkCosts(pt);
}
bool AiInterface::isFreeCells(const Vec2i &pos, int size, Field field){
return world->getMap()->isFreeCells(pos, size, field);
}
}}//end namespace

View File

@@ -0,0 +1,93 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#ifndef _GLEST_GAME_AIINTERFACE_H_
#define _GLEST_GAME_AIINTERFACE_H_
#include "world.h"
#include "commander.h"
#include "command.h"
#include "conversion.h"
#include "ai.h"
using Shared::Util::intToStr;
namespace Glest{ namespace Game{
// =====================================================
// class AiInterface
//
/// The AI will interact with the game through this interface
// =====================================================
class AiInterface{
private:
World *world;
Commander *commander;
Console *console;
Ai ai;
int timer;
int factionIndex;
int teamIndex;
//config
bool redir;
int logLevel;
public:
AiInterface(Game &game, int factionIndex, int teamIndex);
//main
void update();
//get
int getTimer() const {return timer;}
int getFactionIndex() const {return factionIndex;}
//misc
void printLog(int logLevel, const string &s);
//interact
CommandResult giveCommand(int unitIndex, CommandClass commandClass, const Vec2i &pos=Vec2i(0));
CommandResult giveCommand(int unitIndex, const CommandType *commandType, const Vec2i &pos, const UnitType* unitType);
CommandResult giveCommand(int unitIndex, const CommandType *commandType, const Vec2i &pos);
CommandResult giveCommand(int unitIndex, const CommandType *commandType, Unit *u= NULL);
//get data
const ControlType getControlType();
int getMapMaxPlayers();
Vec2i getHomeLocation();
Vec2i getStartLocation(int locationIndex);
int getFactionCount();
int getMyUnitCount() const;
int getMyUpgradeCount() const;
int onSightUnitCount();
const Resource *getResource(const ResourceType *rt);
const Unit *getMyUnit(int unitIndex);
const Unit *getOnSightUnit(int unitIndex);
const FactionType *getMyFactionType();
const TechTree *getTechTree();
bool getNearestSightedResource(const ResourceType *rt, const Vec2i &pos, Vec2i &resultPos);
bool isAlly(const Unit *unit) const;
bool isAlly(int factionIndex) const;
bool reqsOk(const RequirableType *rt);
bool reqsOk(const CommandType *ct);
bool checkCosts(const ProducibleType *pt);
bool isFreeCells(const Vec2i &pos, int size, Field field);
private:
string getLogFilename() const {return "ai"+intToStr(factionIndex)+".log";}
};
}}//end namespace
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
// ============================================================== // ==============================================================
// This file is part of Glest (www.glest.org) // This file is part of Glest (www.glest.org)
// //
// Copyright (C) 2001-2008 Marti<74>o Figueroa // Copyright (C) 2001-2008 Marti<74>o Figueroa
// //
// You can redistribute this code and/or modify it under // You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published // the terms of the GNU General Public License as published
@@ -55,11 +55,11 @@ string getAboutString2(int i){
string getTeammateName(int i){ string getTeammateName(int i){
switch(i){ switch(i){
case 0: return "Marti<EFBFBD>o Figueroa"; case 0: return "Marti<EFBFBD>o Figueroa";
case 1: return "Jos<EFBFBD> Luis Gonz<6E>lez"; case 1: return "Jos<EFBFBD> Luis Gonz<6E>lez";
case 2: return "Tucho Fern<72>ndez"; case 2: return "Tucho Fern<72>ndez";
case 3: return "Jos<EFBFBD> Zanni"; case 3: return "Jos<EFBFBD> Zanni";
case 4: return "F<EFBFBD>lix Men<65>ndez"; case 4: return "F<EFBFBD>lix Men<65>ndez";
case 5: return "Marcos Caruncho"; case 5: return "Marcos Caruncho";
case 6: return "Matthias Braun"; case 6: return "Matthias Braun";
case 7: return "Titus Tscharntke"; case 7: return "Titus Tscharntke";

View File

@@ -1,7 +1,7 @@
// ============================================================== // ==============================================================
// This file is part of Glest (www.glest.org) // This file is part of Glest (www.glest.org)
// //
// Copyright (C) 2001-2008 Marti<74>o Figueroa // Copyright (C) 2001-2008 Marti<74>o Figueroa
// //
// You can redistribute this code and/or modify it under // You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published // the terms of the GNU General Public License as published

View File

@@ -1,7 +1,7 @@
// ============================================================== // ==============================================================
// This file is part of Glest (www.glest.org) // This file is part of Glest (www.glest.org)
// //
// Copyright (C) 2001-2008 Marti<74>o Figueroa // Copyright (C) 2001-2008 Marti<74>o Figueroa
// //
// You can redistribute this code and/or modify it under // You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published // the terms of the GNU General Public License as published
@@ -415,19 +415,18 @@ void Game::mouseDoubleClickLeft(int x, int y){
} }
void Game::mouseMove(int x, int y, const MouseState *ms){ void Game::mouseMove(int x, int y, const MouseState *ms){
const Metrics &metrics = Metrics::getInstance(); const Metrics &metrics = Metrics::getInstance();
mouseX = x; mouseX = x;
mouseY = y; mouseY = y;
if (ms->get(mbCenter)) { if (ms->get(mbCenter)) {
/*if (input.isCtrlDown()) { //if (input.isCtrlDown()) {
float speed = input.isShiftDown() ? 1.f : 0.125f; // float speed = input.isShiftDown() ? 1.f : 0.125f;
float response = input.isShiftDown() ? 0.1875f : 0.0625f; // float response = input.isShiftDown() ? 0.1875f : 0.0625f;
gameCamera.moveForwardH((y - lastMousePos.y) * speed, response); // gameCamera.moveForwardH((y - lastMousePos.y) * speed, response);
gameCamera.moveSideH((x - lastMousePos.x) * speed, response); // gameCamera.moveSideH((x - lastMousePos.x) * speed, response);
} else*/ //} else
{ {
//float ymult = Config::getInstance().getCameraInvertYAxis() ? -0.2f : 0.2f; //float ymult = Config::getInstance().getCameraInvertYAxis() ? -0.2f : 0.2f;
//float xmult = Config::getInstance().getCameraInvertXAxis() ? -0.2f : 0.2f; //float xmult = Config::getInstance().getCameraInvertXAxis() ? -0.2f : 0.2f;
@@ -441,30 +440,36 @@ void Game::mouseMove(int x, int y, const MouseState *ms){
//main window //main window
if (y < 10) { if (y < 10) {
gameCamera.setMoveZ(-scrollSpeed); gameCamera.setMoveZ(-scrollSpeed);
} else if (y > metrics.getVirtualH() - 10) { }
else if (y > metrics.getVirtualH() - 10) {
gameCamera.setMoveZ(scrollSpeed); gameCamera.setMoveZ(scrollSpeed);
} else { }
else {
gameCamera.setMoveZ(0); gameCamera.setMoveZ(0);
} }
if (x < 10) { if (x < 10) {
gameCamera.setMoveX(-scrollSpeed); gameCamera.setMoveX(-scrollSpeed);
} else if (x > metrics.getVirtualW() - 10) { }
else if (x > metrics.getVirtualW() - 10) {
gameCamera.setMoveX(scrollSpeed); gameCamera.setMoveX(scrollSpeed);
} else { }
else {
gameCamera.setMoveX(0); gameCamera.setMoveX(0);
} }
if (mainMessageBox.getEnabled()) { if (mainMessageBox.getEnabled()) {
mainMessageBox.mouseMove(x, y); mainMessageBox.mouseMove(x, y);
} else if (ScriptManager::getMessageBox()->getEnabled()) {
ScriptManager::getMessageBox()->mouseMove(x, y);
//} else if (saveBox) {
// saveBox->mouseMove(x, y);
} else {
//graphics
gui.mouseMoveGraphics(x, y);
} }
if (scriptManager.getMessageBox()->getEnabled()) {
scriptManager.getMessageBox()->mouseMove(x, y);
}
//else if (saveBox) {
// saveBox->mouseMove(x, y);
//} else {
// //graphics
gui.mouseMoveGraphics(x, y);
//}
} }
//display //display

View File

@@ -34,9 +34,6 @@ PlayerModifiers::PlayerModifiers(){
// ===================================================== // =====================================================
// class ScriptManager // class ScriptManager
// ===================================================== // =====================================================
GraphicMessageBox ScriptManager::messageBox;
ScriptManager* ScriptManager::thisScriptManager= NULL; ScriptManager* ScriptManager::thisScriptManager= NULL;
const int ScriptManager::messageWrapCount= 30; const int ScriptManager::messageWrapCount= 30;
const int ScriptManager::displayTextWrapCount= 64; const int ScriptManager::displayTextWrapCount= 64;

View File

@@ -83,7 +83,7 @@ private:
//misc //misc
MessageQueue messageQueue; MessageQueue messageQueue;
static GraphicMessageBox messageBox; GraphicMessageBox messageBox;
string displayText; string displayText;
//last created unit //last created unit
@@ -110,7 +110,7 @@ public:
//message box functions //message box functions
bool getMessageBoxEnabled() const {return !messageQueue.empty();} bool getMessageBoxEnabled() const {return !messageQueue.empty();}
static GraphicMessageBox* getMessageBox() {return &messageBox;} GraphicMessageBox* getMessageBox() {return &messageBox;}
string getDisplayText() const {return displayText;} string getDisplayText() const {return displayText;}
bool getGameOver() const {return gameOver;} bool getGameOver() const {return gameOver;}
const PlayerModifiers *getPlayerModifiers(int factionIndex) const {return &playerModifiers[factionIndex];} const PlayerModifiers *getPlayerModifiers(int factionIndex) const {return &playerModifiers[factionIndex];}

View File

@@ -1,7 +1,7 @@
// ============================================================== // ==============================================================
// This file is part of Glest (www.glest.org) // This file is part of Glest (www.glest.org)
// //
// Copyright (C) 2001-2008 Marti<74>o Figueroa // Copyright (C) 2001-2008 Marti<74>o Figueroa
// //
// You can redistribute this code and/or modify it under // You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published // the terms of the GNU General Public License as published

View File

@@ -1,11 +1,11 @@
// ============================================================== // ==============================================================
// This file is part of Glest (www.glest.org) // This file is part of Glest (www.glest.org)
// //
// Copyright (C) 2001-2008 Marti<74>o Figueroa // Copyright (C) 2001-2008 Marti<74>o Figueroa
// //
// You can redistribute this code and/or modify it under // You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published // the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the // by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version // License, or (at your option) any later version
// ============================================================== // ==============================================================
@@ -26,7 +26,7 @@ namespace Glest{ namespace Game{
// ===================================================== // =====================================================
void Selection::init(Gui *gui, int factionIndex){ void Selection::init(Gui *gui, int factionIndex){
this->factionIndex= factionIndex; this->factionIndex= factionIndex;
this->gui= gui; this->gui= gui;
} }
@@ -41,7 +41,7 @@ void Selection::select(Unit *unit){
return; return;
} }
//check if already selected //check if already selected
for(int i=0; i<selectedUnits.size(); ++i){ for(int i=0; i<selectedUnits.size(); ++i){
if(selectedUnits[i]==unit){ if(selectedUnits[i]==unit){
return; return;
@@ -79,7 +79,7 @@ void Selection::select(Unit *unit){
} }
void Selection::select(const UnitContainer &units){ void Selection::select(const UnitContainer &units){
//add units to gui //add units to gui
for(UnitIterator it= units.begin(); it!=units.end(); ++it){ for(UnitIterator it= units.begin(); it!=units.end(); ++it){
select(*it); select(*it);
@@ -87,7 +87,7 @@ void Selection::select(const UnitContainer &units){
} }
void Selection::unSelect(const UnitContainer &units){ void Selection::unSelect(const UnitContainer &units){
//add units to gui //add units to gui
for(UnitIterator it= units.begin(); it!=units.end(); ++it){ for(UnitIterator it= units.begin(); it!=units.end(); ++it){
for(int i=0; i<selectedUnits.size(); ++i){ for(int i=0; i<selectedUnits.size(); ++i){
@@ -104,7 +104,7 @@ void Selection::unSelect(int i){
gui->onSelectionChanged(); gui->onSelectionChanged();
} }
void Selection::clear(){ void Selection::clear(){
//clear list //clear list
selectedUnits.clear(); selectedUnits.clear();
} }
@@ -127,17 +127,17 @@ bool Selection::isUniform() const{
bool Selection::isEnemy() const{ bool Selection::isEnemy() const{
return selectedUnits.size()==1 && selectedUnits.front()->getFactionIndex()!=factionIndex; return selectedUnits.size()==1 && selectedUnits.front()->getFactionIndex()!=factionIndex;
} }
bool Selection::isComandable() const{ bool Selection::isComandable() const{
return return
!isEmpty() && !isEmpty() &&
!isEnemy() && !isEnemy() &&
!(selectedUnits.size()==1 && !selectedUnits.front()->isOperative()); !(selectedUnits.size()==1 && !selectedUnits.front()->isOperative());
} }
bool Selection::isCancelable() const{ bool Selection::isCancelable() const{
return return
selectedUnits.size()>1 || selectedUnits.size()>1 ||
(selectedUnits.size()==1 && selectedUnits[0]->anyCommand()); (selectedUnits.size()==1 && selectedUnits[0]->anyCommand());
} }
@@ -204,4 +204,4 @@ void Selection::unitEvent(UnitObserver::Event event, const Unit *unit){
} }
} }
}}//end namespace }}//end namespace

View File

@@ -1,7 +1,7 @@
// ============================================================== // ==============================================================
// This file is part of Glest (www.glest.org) // This file is part of Glest (www.glest.org)
// //
// Copyright (C) 2001-2008 Marti<74>o Figueroa // Copyright (C) 2001-2008 Marti<74>o Figueroa
// //
// You can redistribute this code and/or modify it under // You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published // the terms of the GNU General Public License as published

View File

@@ -125,19 +125,6 @@ void MainWindow::eventMouseDown(int x, int y, MouseButton mouseButton){
default: default:
break; break;
} }
/*
switch(mouseButton){
case mbLeft:
program->mouseDownLeft(x, getH() - y);
break;
case mbRight:
program->mouseDownRight(x, getH() - y);
break;
default:
break;
}
*/
} }
void MainWindow::eventMouseUp(int x, int y, MouseButton mouseButton){ void MainWindow::eventMouseUp(int x, int y, MouseButton mouseButton){
@@ -161,12 +148,6 @@ void MainWindow::eventMouseUp(int x, int y, MouseButton mouseButton){
default: default:
break; break;
} }
/*
if(mouseButton==mbLeft){
program->mouseUpLeft(x, getH() - y);
}
*/
} }
void MainWindow::eventMouseDoubleClick(int x, int y, MouseButton mouseButton){ void MainWindow::eventMouseDoubleClick(int x, int y, MouseButton mouseButton){
@@ -190,12 +171,6 @@ void MainWindow::eventMouseDoubleClick(int x, int y, MouseButton mouseButton){
default: default:
break; break;
} }
/*
if(mouseButton == mbLeft){
program->mouseDoubleClickLeft(x, getH() - y);
}
*/
} }
void MainWindow::eventMouseMove(int x, int y, const MouseState *ms){ void MainWindow::eventMouseMove(int x, int y, const MouseState *ms){
@@ -206,8 +181,6 @@ void MainWindow::eventMouseMove(int x, int y, const MouseState *ms){
ProgramState *programState = program->getState(); ProgramState *programState = program->getState();
programState->mouseMove(vx, vy, ms); programState->mouseMove(vx, vy, ms);
//program->mouseMove(x, getH() - y, ms);
} }
void MainWindow::eventMouseWheel(int x, int y, int zDelta) { void MainWindow::eventMouseWheel(int x, int y, int zDelta) {
@@ -222,10 +195,6 @@ void MainWindow::eventMouseWheel(int x, int y, int zDelta) {
programState->eventMouseWheel(vx, vy, zDelta); programState->eventMouseWheel(vx, vy, zDelta);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//program->eventMouseWheel(x, y, zDelta);
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }
void MainWindow::eventKeyDown(char key){ void MainWindow::eventKeyDown(char key){
@@ -285,6 +254,7 @@ int glestMain(int argc, char** argv){
NetworkInterface::setDisplayMessageFunction(ExceptionHandler::DisplayMessage); NetworkInterface::setDisplayMessageFunction(ExceptionHandler::DisplayMessage);
showCursor(config.getBool("Windowed")); showCursor(config.getBool("Windowed"));
//showCursor(false);
program= new Program(); program= new Program();
mainWindow= new MainWindow(program); mainWindow= new MainWindow(program);

View File

@@ -155,62 +155,6 @@ Program::~Program(){
singleton = NULL; singleton = NULL;
} }
void Program::eventMouseDown(int x, int y, MouseButton mouseButton) {
const Metrics &metrics = Metrics::getInstance();
int vx = metrics.toVirtualX(x);
int vy = metrics.toVirtualY(window->getH() - y);
switch(mouseButton) {
case mbLeft:
programState->mouseDownLeft(vx, vy);
break;
case mbRight:
programState->mouseDownRight(vx, vy);
break;
case mbCenter:
programState->mouseDownCenter(vx, vy);
break;
default:
break;
}
}
void Program::mouseDownLeft(int x, int y){
const Metrics &metrics= Metrics::getInstance();
programState->mouseDownLeft(metrics.toVirtualX(x), metrics.toVirtualY(y));
}
void Program::mouseUpLeft(int x, int y){
const Metrics &metrics= Metrics::getInstance();
programState->mouseUpLeft(metrics.toVirtualX(x), metrics.toVirtualY(y));
}
void Program::mouseDownRight(int x, int y){
const Metrics &metrics= Metrics::getInstance();
programState->mouseDownRight(metrics.toVirtualX(x), metrics.toVirtualY(y));
}
void Program::mouseDoubleClickLeft(int x, int y){
const Metrics &metrics= Metrics::getInstance();
programState->mouseDoubleClickLeft(metrics.toVirtualX(x), metrics.toVirtualY(y));
}
void Program::eventMouseWheel(int x, int y, int zDelta) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
const Metrics &metrics= Metrics::getInstance();
int vx = metrics.toVirtualX(x);
int vy = metrics.toVirtualY(window->getH() - y);
programState->eventMouseWheel(vx, vy, zDelta);
}
void Program::mouseMove(int x, int y, const MouseState *ms){
const Metrics &metrics= Metrics::getInstance();
programState->mouseMove(metrics.toVirtualX(x), metrics.toVirtualY(y), ms);
}
void Program::keyDown(char key){ void Program::keyDown(char key){
//delegate event //delegate event
programState->keyDown(key); programState->keyDown(key);

View File

@@ -119,18 +119,10 @@ public:
void initClient(WindowGl *window, const Ip &serverIp); void initClient(WindowGl *window, const Ip &serverIp);
//main //main
void mouseDownLeft(int x, int y);
void mouseUpLeft(int x, int y);
void mouseDownRight(int x, int y);
void mouseDoubleClickLeft(int x, int y);
void eventMouseWheel(int x, int y, int zDelta);
void eventMouseDown(int x, int y, MouseButton mouseButton);
void mouseMove(int x, int y, const MouseState *mouseState);
void keyDown(char key); void keyDown(char key);
void keyUp(char key); void keyUp(char key);
void keyPress(char c); void keyPress(char c);
void loop(); void loop();
void resize(SizeState sizeState); void resize(SizeState sizeState);
void showMessage(const char *msg); void showMessage(const char *msg);

View File

@@ -1,7 +1,7 @@
// ============================================================== // ==============================================================
// This file is part of Glest (www.glest.org) // This file is part of Glest (www.glest.org)
// //
// Copyright (C) 2001-2005 Marti<74>o Figueroa // Copyright (C) 2001-2005 Marti<74>o Figueroa
// //
// You can redistribute this code and/or modify it under // You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published // the terms of the GNU General Public License as published

View File

@@ -0,0 +1,294 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "particle_renderer_gl.h"
#include "opengl.h"
#include "texture_gl.h"
#include "model_renderer.h"
#include "math_util.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{ namespace Gl{
// =====================================================
// class ParticleRendererGl
// =====================================================
// ===================== PUBLIC ========================
ParticleRendererGl::ParticleRendererGl(){
assert(bufferSize%4 == 0);
rendering= false;
// init texture coordinates for quads
for(int i= 0; i<bufferSize; i+=4){
texCoordBuffer[i]= Vec2f(0.0f, 1.0f);
texCoordBuffer[i+1]= Vec2f(0.0f, 0.0f);
texCoordBuffer[i+2]= Vec2f(1.0f, 0.0f);
texCoordBuffer[i+3]= Vec2f(1.0f, 1.0f);
}
}
void ParticleRendererGl::renderManager(ParticleManager *pm, ModelRenderer *mr){
//assertions
assertGl();
//push state
glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_DEPTH_BUFFER_BIT | GL_POLYGON_BIT | GL_CURRENT_BIT | GL_LINE_BIT);
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
//init state
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glDisable(GL_LIGHTING);
glDisable(GL_STENCIL_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
//render
rendering= true;
pm->render(this, mr);
rendering= false;
//pop state
glPopClientAttrib();
glPopAttrib();
//assertions
assertGl();
}
void ParticleRendererGl::renderSystem(ParticleSystem *ps){
assertGl();
assert(rendering);
Vec3f rightVector;
Vec3f upVector;
float modelview[16];
//render particles
setBlendMode(ps->getBlendMode());
// get the current modelview state
glGetFloatv(GL_MODELVIEW_MATRIX , modelview);
rightVector= Vec3f(modelview[0], modelview[4], modelview[8]);
upVector= Vec3f(modelview[1], modelview[5], modelview[9]);
// set state
if(ps->getTexture()!=NULL){
glBindTexture(GL_TEXTURE_2D, static_cast<Texture2DGl*>(ps->getTexture())->getHandle());
}
else{
glBindTexture(GL_TEXTURE_2D, 0);
}
glDisable(GL_ALPHA_TEST);
glDisable(GL_FOG);
glAlphaFunc(GL_GREATER, 0.0f);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
//fill vertex buffer with billboards
int bufferIndex= 0;
for(int i=0; i<ps->getAliveParticleCount(); ++i){
const Particle *particle= ps->getParticle(i);
float size= particle->getSize()/2.0f;
Vec3f pos= particle->getPos();
Vec4f color= particle->getColor();
vertexBuffer[bufferIndex] = pos - (rightVector - upVector) * size;
vertexBuffer[bufferIndex+1] = pos - (rightVector + upVector) * size;
vertexBuffer[bufferIndex+2] = pos + (rightVector - upVector) * size;
vertexBuffer[bufferIndex+3] = pos + (rightVector + upVector) * size;
colorBuffer[bufferIndex]= color;
colorBuffer[bufferIndex+1]= color;
colorBuffer[bufferIndex+2]= color;
colorBuffer[bufferIndex+3]= color;
bufferIndex+= 4;
if(bufferIndex >= bufferSize){
bufferIndex= 0;
renderBufferQuads(bufferSize);
}
}
renderBufferQuads(bufferIndex);
assertGl();
}
void ParticleRendererGl::renderSystemLine(ParticleSystem *ps){
assertGl();
assert(rendering);
if(!ps->isEmpty()){
const Particle *particle= ps->getParticle(0);
setBlendMode(ps->getBlendMode());
glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
//fill vertex buffer with lines
int bufferIndex= 0;
glLineWidth(particle->getSize());
for(int i=0; i<ps->getAliveParticleCount(); ++i){
particle= ps->getParticle(i);
Vec4f color= particle->getColor();
vertexBuffer[bufferIndex] = particle->getPos();
vertexBuffer[bufferIndex+1] = particle->getLastPos();
colorBuffer[bufferIndex]= color;
colorBuffer[bufferIndex+1]= color;
bufferIndex+= 2;
if(bufferIndex >= bufferSize){
bufferIndex= 0;
renderBufferLines(bufferSize);
}
}
renderBufferLines(bufferIndex);
}
assertGl();
}
void ParticleRendererGl::renderSystemLineAlpha(ParticleSystem *ps){
assertGl();
assert(rendering);
if(!ps->isEmpty()){
const Particle *particle= ps->getParticle(0);
setBlendMode(ps->getBlendMode());
glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
//fill vertex buffer with lines
int bufferIndex= 0;
glLineWidth(particle->getSize());
for(int i=0; i<ps->getAliveParticleCount(); ++i){
particle= ps->getParticle(i);
Vec4f color= particle->getColor();
vertexBuffer[bufferIndex] = particle->getPos();
vertexBuffer[bufferIndex+1] = particle->getLastPos();
colorBuffer[bufferIndex]= color;
colorBuffer[bufferIndex+1]= color;
colorBuffer[bufferIndex+1].w= 0.0f;
bufferIndex+= 2;
if(bufferIndex >= bufferSize){
bufferIndex= 0;
renderBufferLines(bufferSize);
}
}
renderBufferLines(bufferIndex);
}
assertGl();
}
void ParticleRendererGl::renderSingleModel(AttackParticleSystem *ps, ModelRenderer *mr){
//render model
if(ps->getModel()!=NULL){
//init
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glColor3f(1.f, 1.f, 1.f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
//translate
Vec3f pos= ps->getPos();
glTranslatef(pos.x, pos.y, pos.z);
//rotate
Vec3f direction= ps->getDirection();
Vec3f flatDirection= Vec3f(direction.x, 0.f, direction.z);
Vec3f rotVector= Vec3f(0.f, 1.f, 0.f).cross(flatDirection);
float angleV= radToDeg(atan2(flatDirection.length(), direction.y)) - 90.f;
glRotatef(angleV, rotVector.x, rotVector.y, rotVector.z);
float angleH= radToDeg(atan2(direction.x, direction.z));
glRotatef(angleH, 0.f, 1.f, 0.f);
//render
mr->begin(true, true, false);
mr->render(ps->getModel());
mr->end();
//end
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
}
}
// ============== PRIVATE =====================================
void ParticleRendererGl::renderBufferQuads(int quadCount){
glVertexPointer(3, GL_FLOAT, 0, vertexBuffer);
glTexCoordPointer(2, GL_FLOAT, 0, texCoordBuffer);
glColorPointer(4, GL_FLOAT, 0, colorBuffer);
glDrawArrays(GL_QUADS, 0, quadCount);
}
void ParticleRendererGl::renderBufferLines(int lineCount){
glVertexPointer(3, GL_FLOAT, 0, vertexBuffer);
glColorPointer(4, GL_FLOAT, 0, colorBuffer);
glDrawArrays(GL_LINES, 0, lineCount);
}
void ParticleRendererGl::setBlendMode(ParticleSystem::BlendMode blendMode){
switch(blendMode){
case ParticleSystem::bmOne:
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
break;
case ParticleSystem::bmOneMinusAlpha:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
default:
assert(false);
}
}
}}} //end namespace