mirror of
https://github.com/glest/glest-source.git
synced 2025-08-19 22:51:24 +02:00
bugfix for scripted scenarios and placing unit model not showing
This commit is contained in:
482
source/glest_game/ai/ai.cpp
Normal file
482
source/glest_game/ai/ai.cpp
Normal 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
189
source/glest_game/ai/ai.h
Normal 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
|
238
source/glest_game/ai/ai_interface.cpp
Normal file
238
source/glest_game/ai/ai_interface.cpp
Normal 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
|
93
source/glest_game/ai/ai_interface.h
Normal file
93
source/glest_game/ai/ai_interface.h
Normal 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
|
1030
source/glest_game/ai/ai_rule.cpp
Normal file
1030
source/glest_game/ai/ai_rule.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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";
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
@@ -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];}
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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
|
||||||
|
294
source/shared_lib/sources/graphics/gl/particle_renderer_gl.cpp
Normal file
294
source/shared_lib/sources/graphics/gl/particle_renderer_gl.cpp
Normal 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
|
Reference in New Issue
Block a user