void CFactoryCAI::GiveCommandReal(const Command& c, bool fromSynced)
{
	// move is always allowed for factories (passed to units it produces)
	if ((c.id == CMD_SET_WANTED_MAX_SPEED) ||
	    ((c.id != CMD_MOVE) && !AllowedCommand(c))) {
		return;
	}

	map<int, BuildOption>::iterator boi = buildOptions.find(c.id);

	// not a build order so queue it to built units
	if (boi == buildOptions.end()) {
		if ((nonQueingCommands.find(c.id) != nonQueingCommands.end()) ||
		    (c.id == CMD_INSERT) || (c.id == CMD_REMOVE) ||
		    (!(c.options & SHIFT_KEY) && ((c.id == CMD_WAIT) || (c.id == CMD_SELFD)))) {
			CCommandAI::GiveAllowedCommand(c);
			return;
		}

		if (!(c.options & SHIFT_KEY)) {
 			waitCommandsAI.ClearUnitQueue(owner, newUnitCommands);
			newUnitCommands.clear();
		}

		if (c.id != CMD_STOP) {
			if ((c.id == CMD_WAIT) || (c.id == CMD_SELFD)) {
				if (!newUnitCommands.empty() && (newUnitCommands.back().id == c.id)) {
					if (c.id == CMD_WAIT) {
						waitCommandsAI.RemoveWaitCommand(owner, c);
					}
					newUnitCommands.pop_back();
				} else {
					newUnitCommands.push_back(c);
				}
			}
			else {
				bool dummy;
				if (CancelCommands(c, newUnitCommands, dummy) > 0) {
					return;
				} else {
					if (GetOverlapQueued(c, newUnitCommands).empty()) {
						newUnitCommands.push_back(c);
					} else {
						return;
					}
				}
			}
		}

		// the first new-unit build order can not be WAIT or SELFD
		while (!newUnitCommands.empty()) {
			const int id = newUnitCommands.front().id;
			if ((id == CMD_WAIT) || (id == CMD_SELFD)) {
				if (c.id == CMD_WAIT) {
					waitCommandsAI.RemoveWaitCommand(owner, c);
				}
				newUnitCommands.pop_front();
			} else {
				break;
			}
		}

		return;
	}

	BuildOption &bo = boi->second;

	int numItems = 1;
	if (c.options & SHIFT_KEY)   { numItems *= 5; }
	if (c.options & CONTROL_KEY) { numItems *= 20; }

	if (c.options & RIGHT_MOUSE_KEY) {
		bo.numQued -= numItems;
		if (bo.numQued < 0) {
			bo.numQued = 0;
		}

		int numToErase = numItems;
		if (c.options & ALT_KEY) {
			for (unsigned int cmdNum = 0; cmdNum < commandQue.size() && numToErase; ++cmdNum) {
				if (commandQue[cmdNum].id == c.id) {
					commandQue[cmdNum].id = CMD_STOP;
					numToErase--;
				}
			}
		}
		else {
			for (int cmdNum = commandQue.size() - 1; cmdNum != -1 && numToErase; --cmdNum) {
				if (commandQue[cmdNum].id == c.id) {
					commandQue[cmdNum].id = CMD_STOP;
					numToErase--;
				}
			}
		}
		UpdateIconName(c.id,bo);
		SlowUpdate();
	}
	else {
		if (c.options & ALT_KEY) {
			for (int a = 0; a < numItems; ++a) {
				if (repeatOrders) {
					Command nc(c);
					nc.options |= DONT_REPEAT;
					if (commandQue.empty()) {
						commandQue.push_front(nc);
					} else {
						commandQue.insert(commandQue.begin()+1, nc);
					}
				} else {
					commandQue.push_front(c);
				}
			}
			if (!repeatOrders) {
				building=false;
				CFactory* fac = (CFactory*)owner;
				fac->StopBuild();
			}
		} else {
			for (int a = 0; a < numItems; ++a) {
				commandQue.push_back(c);
			}
		}
		bo.numQued += numItems;
		UpdateIconName(c.id, bo);

		SlowUpdate();
	}
}
Example #2
0
void CCommandAI::GiveAllowedCommand(const Command& c, bool fromSynced)
{
	if (ExecuteStateCommand(c)) {
		return;
	}

	switch (c.id) {
		case CMD_SELFD: {
			if (owner->unitDef->canSelfD) {
				if (!(c.options & SHIFT_KEY) || commandQue.empty()) {
					if (owner->selfDCountdown != 0) {
						owner->selfDCountdown = 0;
					} else {
						owner->selfDCountdown = owner->unitDef->selfDCountdown*2+1;
					}
				}
				else {
				if (commandQue.back().id == CMD_SELFD) {
					commandQue.pop_back();
					} else {
						commandQue.push_back(c);
					}
				}
			}
			return;
		}
		case CMD_SET_WANTED_MAX_SPEED: {
			if (CanSetMaxSpeed() &&
			    (commandQue.empty() ||
			     (commandQue.back().id != CMD_SET_WANTED_MAX_SPEED))) {
				// bail early, do not check for overlaps or queue cancelling
				commandQue.push_back(c);
				if (commandQue.size()==1 && !owner->beingBuilt) {
					SlowUpdate();
				}
			}
			return;
		}
		case CMD_WAIT: {
			GiveWaitCommand(c);
			return;
		}
		case CMD_INSERT: {
			ExecuteInsert(c, fromSynced);
			return;
		}
		case CMD_REMOVE: {
			ExecuteRemove(c);
			return;
		}
	}

	// flush the queue for immediate commands
	if (!(c.options & SHIFT_KEY)) {
		if (!commandQue.empty()) {
			if ((commandQue.front().id == CMD_DGUN)      ||
			    (commandQue.front().id == CMD_ATTACK)    ||
			    (commandQue.front().id == CMD_AREA_ATTACK)) {
				owner->AttackUnit(0,true);
			}
			waitCommandsAI.ClearUnitQueue(owner, commandQue);
			commandQue.clear();
		}
		inCommand=false;
		if(orderTarget){
			DeleteDeathDependence(orderTarget);
			orderTarget=0;
		}
	}

	if (c.id == CMD_PATROL) {
		CCommandQueue::iterator ci = commandQue.begin();
		for (; ci != commandQue.end() && ci->id != CMD_PATROL; ci++) {
			// just increment
		}
		if (ci == commandQue.end()) {
			if (commandQue.empty()) {
				Command c2;
				c2.id = CMD_PATROL;
				c2.params.push_back(owner->pos.x);
				c2.params.push_back(owner->pos.y);
				c2.params.push_back(owner->pos.z);
				c2.options = c.options;
				commandQue.push_back(c2);
			}
			else {
				do {
					ci--;
					if (ci->params.size() >= 3) {
						Command c2;
						c2.id = CMD_PATROL;
						c2.params = ci->params;
						c2.options = c.options;
						commandQue.push_back(c2);
						break;
					} else if (ci == commandQue.begin()) {
						Command c2;
						c2.id = CMD_PATROL;
						c2.params.push_back(owner->pos.x);
						c2.params.push_back(owner->pos.y);
						c2.params.push_back(owner->pos.z);
						c2.options = c.options;
						commandQue.push_back(c2);
						break;
					}
				}
				while (ci != commandQue.begin());
			}
		}
	}

	// cancel duplicated commands
	bool first;
	if (CancelCommands(c, commandQue, first) > 0) {
		if (first) {
			Command stopCommand;
			stopCommand.id = CMD_STOP;
			commandQue.push_front(stopCommand);
			SlowUpdate();
		}
		return;
	}

	// do not allow overlapping commands
	if (!GetOverlapQueued(c).empty()) {
		return;
	}

	if (c.id == CMD_ATTACK) {
		// avoid weaponless units moving to 0 distance when given attack order
		if (owner->weapons.empty() && (owner->unitDef->canKamikaze == false)) {
			Command c2;
			c2.id = CMD_STOP;
			commandQue.push_back(c2);
			return;
		}
	}

	commandQue.push_back(c);

	if (commandQue.size() == 1 && !owner->beingBuilt && !owner->stunned) {
		SlowUpdate();
	}
}
Example #3
0
void CCommandAI::GiveAllowedCommand(const Command& c, bool fromSynced)
{
	if (ExecuteStateCommand(c)) {
		return;
	}

	switch (c.GetID()) {
		case CMD_SELFD: {
			if (owner->unitDef->canSelfD) {
				if (!(c.options & SHIFT_KEY) || commandQue.empty()) {
					if (owner->selfDCountdown != 0) {
						owner->selfDCountdown = 0;
					} else {
						owner->selfDCountdown = owner->unitDef->selfDCountdown*2+1;
					}
				}
				else if (commandQue.back().GetID() == CMD_SELFD) {
					commandQue.pop_back();
				} else {
					commandQue.push_back(c);
				}
			}
			return;
		}
		case CMD_SET_WANTED_MAX_SPEED: {
			if (CanSetMaxSpeed() &&
			    (commandQue.empty() ||
			     (commandQue.back().GetID() != CMD_SET_WANTED_MAX_SPEED))) {
				// bail early, do not check for overlaps or queue cancelling
				commandQue.push_back(c);
				if (commandQue.size()==1 && !owner->beingBuilt) {
					SlowUpdate();
				}
			}
			return;
		}
		case CMD_WAIT: {
			GiveWaitCommand(c);
			return;
		}
		case CMD_INSERT: {
			ExecuteInsert(c, fromSynced);
			return;
		}
		case CMD_REMOVE: {
			ExecuteRemove(c);
			return;
		}
	}

	// flush the queue for immediate commands
	// NOTE: CMD_STOP can be a queued order (!)
	if (!(c.options & SHIFT_KEY)) {
		waitCommandsAI.ClearUnitQueue(owner, commandQue);
		ClearTargetLock((commandQue.empty())? Command(CMD_STOP): commandQue.front());
		ClearCommandDependencies();
		SetOrderTarget(NULL);

		// if c is an attack command, the actual order-target
		// gets set via ExecuteAttack (called from SlowUpdate
		// at the end of this function)
		commandQue.clear();
		assert(commandQue.empty());

		inCommand = false;
	}

	AddCommandDependency(c);

	if (c.GetID() == CMD_PATROL) {
		CCommandQueue::iterator ci = commandQue.begin();
		for (; ci != commandQue.end() && ci->GetID() != CMD_PATROL; ++ci) {
			// just increment
		}
		if (ci == commandQue.end()) {
			if (commandQue.empty()) {
				Command c2(CMD_PATROL, c.options, owner->pos);
				commandQue.push_back(c2);
			} else {
				do {
					--ci;
					if (ci->params.size() >= 3) {
						Command c2(CMD_PATROL, c.options);
						c2.params = ci->params;
						commandQue.push_back(c2);
						break;
					} else if (ci == commandQue.begin()) {
						Command c2(CMD_PATROL, c.options, owner->pos);
						commandQue.push_back(c2);
						break;
					}
				}
				while (ci != commandQue.begin());
			}
		}
	}

	// cancel duplicated commands
	bool first;
	if (CancelCommands(c, commandQue, first) > 0) {
		if (first) {
			Command stopCommand(CMD_STOP);
			commandQue.push_front(stopCommand);
			SlowUpdate();
		}
		return;
	}

	// do not allow overlapping commands
	if (!GetOverlapQueued(c).empty()) {
		return;
	}

	if (c.GetID() == CMD_ATTACK) {
		// avoid weaponless units moving to 0 distance when given attack order
		if (owner->weapons.empty() && (!owner->unitDef->canKamikaze)) {
			Command c2(CMD_STOP);
			commandQue.push_back(c2);
			return;
		}
	}

	commandQue.push_back(c);

	if (commandQue.size() == 1 && !owner->beingBuilt && !owner->IsStunned()) {
		SlowUpdate();
	}
}
Example #4
0
void CFactoryCAI::GiveCommandReal(const Command& c, bool fromSynced)
{
	const int cmdID = c.GetID();
	
	// move is always allowed for factories (passed to units it produces)
	if ((cmdID == CMD_SET_WANTED_MAX_SPEED) ||
	    ((cmdID != CMD_MOVE) && !AllowedCommand(c, fromSynced))) {
		return;
	}

	map<int, BuildOption>::iterator boi = buildOptions.find(cmdID);

	// not a build order (or a build order we do not support, eg. if multiple
	// factories of different types were selected) so queue it to built units
	if (boi == buildOptions.end()) {
		if (cmdID < 0)
			return;

		if ((nonQueingCommands.find(cmdID) != nonQueingCommands.end()) ||
		    (cmdID == CMD_INSERT) || (cmdID == CMD_REMOVE) ||
		    (!(c.options & SHIFT_KEY) && ((cmdID == CMD_WAIT) || (cmdID == CMD_SELFD)))) {
			CCommandAI::GiveAllowedCommand(c);
			return;
		}

		if (!(c.options & SHIFT_KEY)) {
 			waitCommandsAI.ClearUnitQueue(owner, newUnitCommands);
			CCommandAI::ClearCommandDependencies();
			newUnitCommands.clear();
		}

		CCommandAI::AddCommandDependency(c);

		if (cmdID != CMD_STOP) {
			if ((cmdID == CMD_WAIT) || (cmdID == CMD_SELFD)) {
				if (!newUnitCommands.empty() && (newUnitCommands.back().GetID() == cmdID)) {
					if (cmdID == CMD_WAIT) {
						waitCommandsAI.RemoveWaitCommand(owner, c);
					}
					newUnitCommands.pop_back();
				} else {
					newUnitCommands.push_back(c);
				}
			} else {
				bool dummy;
				if (CancelCommands(c, newUnitCommands, dummy) > 0) {
					return;
				} else {
					if (GetOverlapQueued(c, newUnitCommands).empty()) {
						newUnitCommands.push_back(c);
					} else {
						return;
					}
				}
			}
		}

		// the first new-unit build order can not be WAIT or SELFD
		while (!newUnitCommands.empty()) {
			const Command& newUnitCommand = newUnitCommands.front();
			const int id = newUnitCommand.GetID();

			if ((id == CMD_WAIT) || (id == CMD_SELFD)) {
				if (cmdID == CMD_WAIT) {
					waitCommandsAI.RemoveWaitCommand(owner, c);
				}
				newUnitCommands.pop_front();
			} else {
				break;
			}
		}

		return;
	}

	BuildOption& bo = boi->second;
	int numItems = 1;

	if (c.options & SHIFT_KEY)   { numItems *= 5; }
	if (c.options & CONTROL_KEY) { numItems *= 20; }

	if (c.options & RIGHT_MOUSE_KEY) {
		bo.numQued -= numItems;
		bo.numQued  = std::max(bo.numQued, 0);

		int numToErase = numItems;
		if (c.options & ALT_KEY) {
			for (unsigned int cmdNum = 0; cmdNum < commandQue.size() && numToErase; ++cmdNum) {
				if (commandQue[cmdNum].GetID() == cmdID) {
					commandQue[cmdNum] = Command(CMD_STOP);
					numToErase--;
				}
			}
		} else {
			for (int cmdNum = commandQue.size() - 1; cmdNum != -1 && numToErase; --cmdNum) {
				if (commandQue[cmdNum].GetID() == cmdID) {
					commandQue[cmdNum] = Command(CMD_STOP);
					numToErase--;
				}
			}
		}
		UpdateIconName(cmdID, bo);
		SlowUpdate();
	} else {
		if (c.options & ALT_KEY) {
			for (int a = 0; a < numItems; ++a) {
				if (repeatOrders) {
					Command nc(c);
					nc.options |= INTERNAL_ORDER;
					if (commandQue.empty()) {
						commandQue.push_front(nc);
					} else {
						commandQue.insert(commandQue.begin()+1, nc);
					}
				} else {
					commandQue.push_front(c);
				}
			}
			if (!repeatOrders) {
				CFactory* fac = static_cast<CFactory*>(owner);
				fac->StopBuild();
			}
		} else {
			for (int a = 0; a < numItems; ++a) {
				commandQue.push_back(c);
			}
		}
		bo.numQued += numItems;
		UpdateIconName(cmdID, bo);

		SlowUpdate();
	}
}
Example #5
0
void PopSession::CheckQueue()
{
	MojLogDebug(m_log, "PopSession: Checking the queue. Current state: %d", m_state);

	switch(m_state)
	{
		case State_None:
		{
			MojLogCritical(m_log, "unable to run commands, no account available");
			break;
		}
		case State_NeedsConnection:
		{
			MojLogInfo(m_log, "State: NeedsConnection");
			MojRefCountedPtr<ConnectCommand> command(new ConnectCommand(*this));
			m_commandManager->RunCommand(command);
			m_state = State_Connecting;
			m_canShutdown = false;

			break;
		}
		case State_Connecting:
		{
			MojLogInfo(m_log, "State: Connecting");
			break;
		}
		case State_CheckTlsSupport:
		{
			MojLogInfo(m_log, "State: CheckTlsSupport");
			MojRefCountedPtr<CheckTlsCommand> command(new CheckTlsCommand(*this));
			m_commandManager->RunCommand(command);
			m_state = State_PendingTlsSupport;

			break;
		}
		case State_NegotiateTlsConnection:
		{
			MojLogInfo(m_log, "State: NegotiateTlsConnect");
			MojRefCountedPtr<NegotiateTlsCommand> command(new NegotiateTlsCommand(*this));
			m_commandManager->RunCommand(command);
			m_state = State_PendingTlsNegotiation;

			break;
		}
		case State_UsernameRequired:
		{
			MojLogInfo(m_log, "State: UsernameRequired");
			MojRefCountedPtr<UserCommand> command(new UserCommand(*this, m_account->GetUsername()));
			m_commandManager->RunCommand(command);
			m_state = State_PendingLogin;

			break;
		}
		case State_PasswordRequired:
		{
			MojLogInfo(m_log, "State: PasswordRequired");
			MojRefCountedPtr<PasswordCommand> command(new PasswordCommand(*this, m_account->GetPassword()));
			m_commandManager->RunCommand(command);
			m_state = State_PendingLogin;

			break;
		}
		case State_PendingLogin:
		{
			break;
		}
		case State_NeedUidMap:
		{
			MojLogInfo(m_log, "State: NeedUidMap");
			MojRefCountedPtr<CreateUidMapCommand> command(new CreateUidMapCommand(*this, m_uidMap));
			m_commandManager->RunCommand(command);
			m_state = State_GettingUidMap;

			break;
		}
		case State_GettingUidMap:
		{
			MojLogInfo(m_log, "State: GettingUidMap");
			break;
		}
		case State_OkToSync:
		{
			MojLogInfo(m_log, "State: OkToSync");
			MojLogInfo(m_log, "%i command(s) to run in queue", m_commandManager->GetPendingCommandCount());
			m_commandManager->Resume();
			RunCommandsInQueue();

			break;
		}
		case State_CancelPendingCommands:
		{
			MojLogInfo(m_log, "State: CancelPendingCommands");
			CancelCommands();

			break;
		}
		case State_InvalidCredentials:
		{
			break;
		}
		case State_AccountDisabled:
		{
			MojLogInfo(m_log, "State: AccountDisabled");
			CancelCommands();

			break;
		}
		case State_AccountDeleted:
		{
			break;
		}
		case State_LogOut:
		{
			MojLogInfo(m_log, "State: LogOut");
			LogOut();

			break;
		}
		case State_LoggingOut:
		{
			break;
		}
		default:
		{

		}
	}
}