MegaGlest/source/glest_game/type_instances/command.cpp
Banestorm 35ff02052c
Remove command priority system
This was resulting in non-intuitive and surprising behaviour when queuing
commands. Removing this system results in Megaglest behaving more like
other RTS games.

For instance, the following are now possible and weren't previously:
- Queuing multiple attack ground commands to move along a specific path
attacking all enemies on the way.
- Queuing attack ground followed by hold position, which is a sensible
  thing to do if you want a unit to guard a specific area.
- Queuing a move command followed by a produce command, if you want to
  have your summoner summon a daemon at a specific location.

The behaviour of queuing the stop command is unchanged, and commands that
must be the last in the queue, such as morphing, are still properly replaced when something
else is queued.
2022-09-06 02:11:05 +04:00

231 lines
7.7 KiB
C++

// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martiñ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 "command.h"
#include "command_type.h"
#include "util.h"
#include "conversion.h"
#include "unit_type.h"
#include "faction.h"
#include "world.h"
#include "leak_dumper.h"
using namespace Shared::Util;
namespace Glest{ namespace Game{
// =====================================================
// class Command
// =====================================================
Command::Command() : unitRef() {
this->commandType= NULL;
unitType= NULL;
stateType = cst_None;
stateValue = -1;
unitCommandGroupId = -1;
}
Command::Command(const CommandType *ct, const Vec2i &pos) :unitRef() {
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] ct = [%p]\n",__FILE__,__FUNCTION__,__LINE__,ct);
this->commandType= ct;
this->pos= pos;
this->originalPos = this->pos;
unitType= NULL;
stateType = cst_None;
stateValue = -1;
unitCommandGroupId = -1;
}
Command::Command(const CommandType *ct, Unit* unit) {
this->commandType= ct;
this->pos= Vec2i(0);
this->originalPos = this->pos;
this->unitRef= unit;
unitType= NULL;
if(unit!=NULL) {
//unit->resetHighlight(); is in gui now
pos= unit->getCellPos();
}
stateType = cst_None;
stateValue = -1;
unitCommandGroupId = -1;
}
Command::Command(const CommandType *ct, const Vec2i &pos, const UnitType *unitType, CardinalDir facing) : unitRef() {
this->commandType= ct;
this->pos= pos;
this->originalPos = this->pos;
this->unitType= unitType;
this->facing = facing;
stateType = cst_None;
stateValue = -1;
unitCommandGroupId = -1;
//if(this->unitType != NULL) {
// SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unitType = [%s]\n",__FILE__,__FUNCTION__,__LINE__,this->unitType->toString().c_str());
//}
}
// =============== set ===============
void Command::setCommandType(const CommandType *commandType) {
this->commandType= commandType;
}
void Command::setPos(const Vec2i &pos){
this->pos= pos;
}
//void Command::setOriginalPos(const Vec2i &pos) {
// this->originalPos= pos;
//}
void Command::setPosToOriginalPos() {
this->pos= this->originalPos;
}
void Command::setUnit(Unit *unit){
this->unitRef= unit;
}
std::string Command::toString(bool translatedValue) const {
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__, __LINE__);
std::string result = "";
if(commandType != NULL) {
result = "commandType id = " + intToStr(commandType->getId()) + ", desc = " + commandType->toString(translatedValue);
}
else {
result = "commandType = NULL";
}
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__, __LINE__);
result += ", pos = " + pos.getString() + ", originalPos = " + originalPos.getString() + ", facing = " + intToStr(facing.asInt());
//if(unitRef.getUnit() != NULL) {
if(unitRef.getUnitId() >= 0) {
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__, __LINE__);
result += ", unitRef.getUnit() id = " + intToStr(unitRef.getUnitId());
// The code below causes a STACK OVERFLOW!
//if(unitRef.getUnit() != NULL) {
// result += ", unitRef.getUnit() = " + unitRef.getUnit()->toString();
//}
}
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__, __LINE__);
if(unitType != NULL) {
result += ", unitTypeId = " + intToStr(unitType->getId());
result += ", unitTypeDesc = " + unitType->getReqDesc(translatedValue);
}
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__, __LINE__);
result += ", stateType = " + intToStr(stateType) + ", stateValue = " + intToStr(stateValue);
result += ", unitCommandGroupId = " + intToStr(unitCommandGroupId);
return result;
}
Checksum Command::getCRC() {
Checksum crcForCmd;
crcForCmd.addInt(commandType->getId());
crcForCmd.addInt(originalPos.x);
crcForCmd.addInt(originalPos.y);
crcForCmd.addInt(pos.x);
crcForCmd.addInt(pos.y);
crcForCmd.addInt(unitRef.getUnitId());
crcForCmd.addInt(facing);
if(unitType != NULL) {
crcForCmd.addInt(unitType->getId());
}
crcForCmd.addInt(stateType);
crcForCmd.addInt(stateValue);
crcForCmd.addInt(unitCommandGroupId);
return crcForCmd;
}
void Command::saveGame(XmlNode *rootNode, Faction *faction) {
std::map<string,string> mapTagReplacements;
XmlNode *commandNode = rootNode->addChild("Command");
// const CommandType *commandType;
if(commandType != NULL) {
commandNode->addAttribute("commandType",intToStr(commandType->getId()), mapTagReplacements);
}
// Vec2i originalPos;
commandNode->addAttribute("originalPos",originalPos.getString(), mapTagReplacements);
// Vec2i pos;
commandNode->addAttribute("pos",pos.getString(), mapTagReplacements);
// UnitReference unitRef; //target unit, used to move and attack optionally
unitRef.saveGame(commandNode);
// CardinalDir facing; // facing, for build command
commandNode->addAttribute("facing",intToStr(facing), mapTagReplacements);
// const UnitType *unitType; //used for build
if(unitType != NULL) {
commandNode->addAttribute("unitTypeId",intToStr(unitType->getId()), mapTagReplacements);
commandNode->addAttribute("unitTypeFactionIndex",intToStr(faction->getIndex()), mapTagReplacements);
}
// CommandStateType stateType;
commandNode->addAttribute("stateType",intToStr(stateType), mapTagReplacements);
// int stateValue;
commandNode->addAttribute("stateValue",intToStr(stateValue), mapTagReplacements);
// int unitCommandGroupId;
commandNode->addAttribute("unitCommandGroupId",intToStr(unitCommandGroupId), mapTagReplacements);
}
Command * Command::loadGame(const XmlNode *rootNode,const UnitType *ut,World *world) {
Command *result = new Command();
const XmlNode *commandNode = rootNode;
//description = commandNode->getAttribute("description")->getValue();
// const CommandType *commandType;
if(commandNode->hasAttribute("commandType") == true) {
int cmdTypeId = commandNode->getAttribute("commandType")->getIntValue();
result->commandType = ut->findCommandTypeById(cmdTypeId);
}
// Vec2i originalPos;
result->originalPos = Vec2i::strToVec2(commandNode->getAttribute("originalPos")->getValue());
// Vec2i pos;
result->pos = Vec2i::strToVec2(commandNode->getAttribute("pos")->getValue());
// UnitReference unitRef; //target unit, used to move and attack optionally
result->unitRef.loadGame(commandNode,world);
// CardinalDir facing; // facing, for build command
result->facing = static_cast<CardinalDir>(commandNode->getAttribute("facing")->getIntValue());
// const UnitType *unitType; //used for build
if(commandNode->hasAttribute("unitTypeId") == true) {
//result->unitType = ut;
int unitTypeId = commandNode->getAttribute("unitTypeId")->getIntValue();
int unitTypeFactionIndex = commandNode->getAttribute("unitTypeFactionIndex")->getIntValue();
Faction *faction = world->getFaction(unitTypeFactionIndex);
result->unitType = world->findUnitTypeById(faction->getType(),unitTypeId);
}
// CommandStateType stateType;
result->stateType = static_cast<CommandStateType>(commandNode->getAttribute("stateType")->getIntValue());
// int stateValue;
result->stateValue = commandNode->getAttribute("stateValue")->getIntValue();
// int unitCommandGroupId;
result->unitCommandGroupId = commandNode->getAttribute("unitCommandGroupId")->getIntValue();
return result;
}
}}//end namespace