/**
**  Show the current order of a unit.
**
**  @param unit  Pointer to the unit.
*/
void ShowOrder(const CUnit &unit)
{
	if (unit.Destroyed || unit.Removed) {
		return;
	}
#ifndef DEBUG
	if (!ThisPlayer->IsAllied(unit) && unit.Player != ThisPlayer) {
		return;
	}
#endif
	// Get current position
	const PixelPos mapPos = unit.GetMapPixelPosCenter();
	PixelPos screenStartPos = CurrentViewport->MapToScreenPixelPos(mapPos);
	const bool flushed = unit.Orders[0]->Finished;

	COrderPtr order;
	// If the current order is cancelled show the next one
	if (unit.Orders.size() > 1 && flushed) {
		order = unit.Orders[1];
	} else {
		order = unit.Orders[0];
	}
	PixelPos screenPos = order->Show(*CurrentViewport, screenStartPos);
	// Show the rest of the orders
	for (size_t i = 1 + (flushed ? 1 : 0); i < unit.Orders.size(); ++i) {
		screenPos = unit.Orders[i]->Show(*CurrentViewport, screenPos);
	}

	// Show order for new trained units
	if (unit.NewOrder) {
		unit.NewOrder->Show(*CurrentViewport, screenStartPos);
	}
}
Exemple #2
0
/**
**  Get the location of a unit's order.
**
**  @param unit   Pointer to unit.
**  @param order  Pointer to order.
**  @param x      Resulting screen X cordinate.
**  @param y      Resulting screen Y cordinate.
*/
static void GetOrderPosition(const CUnit &unit, const COrderPtr order, int *x, int *y)
{
	CUnit *goal;

	// FIXME: n0body: Check for goal gone?
	if ((goal = order->GetGoal()) && (!goal->Removed)) {
		// Order has a goal, get it's location.
		*x = CurrentViewport->Map2ViewportX(goal->tilePos.x) + goal->IX +
			goal->Type->TileWidth * TileSizeX / 2;
		*y = CurrentViewport->Map2ViewportY(goal->tilePos.y) + goal->IY +
			goal->Type->TileHeight * TileSizeY / 2;
	} else {
		if (order->goalPos.x >= 0 && order->goalPos.y >= 0) {
			// Order is for a location, show that.
			*x = CurrentViewport->Map2ViewportX(order->goalPos.x) + TileSizeX / 2;
			*y = CurrentViewport->Map2ViewportY(order->goalPos.y) + TileSizeY / 2;
		} else {
			// Some orders ignore x,y (like StandStill).
			// Use the unit's position instead.
			*x = CurrentViewport->Map2ViewportX(unit.tilePos.x) + unit.IX +
				unit.Type->TileWidth * TileSizeX / 2;
			*y = CurrentViewport->Map2ViewportY(unit.tilePos.y) + unit.IY +
				unit.Type->TileHeight * TileSizeY / 2;
		}
		if (order->Action == UnitActionBuild) {
			*x += (order->Arg1.Type->TileWidth - 1) * TileSizeX / 2;
			*y += (order->Arg1.Type->TileHeight - 1) * TileSizeY / 2;
		}
	}
}
/**
**  Check if there's a unit that should be repaired.
*/
static void AiCheckRepair()
{
	int i;
	int j;
	int k;
	int n;
	bool repair_flag;

	n = AiPlayer->Player->TotalNumUnits;
	k = 0;
	// Selector for next unit
	for (i = n - 1; i >= 0; --i) {
		CUnit *unit = AiPlayer->Player->Units[i];
		if (unit && UnitNumber(*unit) == AiPlayer->LastRepairBuilding) {
			k = i + 1;
		}
	}

	for (i = k; i < n; ++i) {
		CUnit &unit = *AiPlayer->Player->Units[i];
		repair_flag = true;

		if (!unit.IsAliveOnMap()) {
			continue;
		}

		// Unit damaged?
		// Don't repair attacked unit (wait 5 sec before repairing)
		if (unit.Type->RepairHP &&
				unit.CurrentAction() != UnitActionBuilt &&
				unit.CurrentAction() != UnitActionUpgradeTo &&
				unit.Variable[HP_INDEX].Value < unit.Variable[HP_INDEX].Max &&
				unit.Attacked + 5 * CYCLES_PER_SECOND < GameCycle) {

			//
			// FIXME: Repair only units under control
			//
			if (AiEnemyUnitsInDistance(unit, unit.Stats->Variables[SIGHTRANGE_INDEX].Max)) {
				continue;
			}
			//
			// Must check, if there are enough resources
			//
			for (j = 1; j < MaxCosts; ++j) {
				if (unit.Stats->Costs[j] &&
						AiPlayer->Player->Resources[j] < 99) {
					repair_flag = false;
					break;
				}
			}

			//
			// Find a free worker, who can build this building can repair it?
			//
			if (repair_flag) {
				AiRepairUnit(unit);
				AiPlayer->LastRepairBuilding = UnitNumber(unit);
				return;
			}
		}
		// Building under construction but no worker
		if (unit.CurrentAction() == UnitActionBuilt) {
			int j;
			for (j = 0; j < AiPlayer->Player->TotalNumUnits; ++j) {
				COrderPtr order = AiPlayer->Player->Units[j]->CurrentOrder();
				if (order->Action == UnitActionRepair && order->GetGoal() == &unit) {
					break;
				}
			}
			if (j == AiPlayer->Player->TotalNumUnits) {
				// Make sure we have enough resources first
				for (j = 0; j < MaxCosts; ++j) {
					// FIXME: the resources don't necessarily have to be in storage
					if (AiPlayer->Player->Resources[j] < unit.Stats->Costs[j]) {
						break;
					}
				}
				if (j == MaxCosts) {
					AiRepairUnit(unit);
					AiPlayer->LastRepairBuilding = UnitNumber(unit);
					return;
				}
			}
		}
	}
	AiPlayer->LastRepairBuilding = 0;
}
Exemple #4
0
/**
**  Save an order.
**
**  @param order  Order who should be saved.
**  @param file   Output file.
*/
void SaveOrder(const COrderPtr order, CFile *file)
{
	file->printf("{");
	switch (order->Action) {
		case UnitActionNone:
			file->printf("\"action-none\",");
			break;

		case UnitActionStill:
			file->printf("\"action-still\",");
			break;
		case UnitActionStandGround:
			file->printf("\"action-stand-ground\",");
			break;
		case UnitActionFollow:
			file->printf("\"action-follow\",");
			break;
		case UnitActionMove:
			file->printf("\"action-move\",");
			break;
		case UnitActionAttack:
			file->printf("\"action-attack\",");
			break;
		case UnitActionAttackGround:
			file->printf("\"action-attack-ground\",");
			break;
		case UnitActionDie:
			file->printf("\"action-die\",");
			break;

		case UnitActionSpellCast:
			file->printf("\"action-spell-cast\",");
			break;

		case UnitActionTrain:
			file->printf("\"action-train\",");
			break;
		case UnitActionUpgradeTo:
			file->printf("\"action-upgrade-to\",");
			break;
		case UnitActionResearch:
			file->printf("\"action-research\",");
			break;
		case UnitActionBuilt:
			file->printf("\"action-built\",");
			break;

		case UnitActionBoard:
			file->printf("\"action-board\",");
			break;
		case UnitActionUnload:
			file->printf("\"action-unload\",");
			break;
		case UnitActionPatrol:
			file->printf("\"action-patrol\",");
			break;
		case UnitActionBuild:
			file->printf("\"action-build\",");
			break;

		case UnitActionRepair:
			file->printf("\"action-repair\",");
			break;
		case UnitActionResource:
			file->printf("\"action-resource\",");
			break;
		case UnitActionReturnGoods:
			file->printf("\"action-return-goods\",");
			break;
		case UnitActionTransformInto:
			file->printf("\"action-transform-into\",");
			break;
		default:
			DebugPrint("Unknown action in order\n");
	}

	file->printf(" \"range\", %d,", order->Range);
	file->printf(" \"width\", %d,", order->Width);
	file->printf(" \"height\", %d,", order->Height);
	file->printf(" \"min-range\", %d,", order->MinRange);
	if (order->HasGoal()) {
		CUnit &goal = *order->GetGoal();
		if (goal.Destroyed) {
			/* this unit is destroyed so it's not in the global unit
			 * array - this means it won't be saved!!! */
			printf ("FIXME: storing destroyed Goal - loading will fail.\n");
		}
		file->printf(" \"goal\", \"%s\",", UnitReference(goal).c_str());
	}
	file->printf(" \"tile\", {%d, %d}", order->goalPos.x, order->goalPos.y);

	// Extra arg.
	switch (order->Action) {
		case UnitActionTrain:
		case UnitActionUpgradeTo:
		case UnitActionBuild:
		case UnitActionTransformInto:
			file->printf(", \"type\", \"%s\"", order->Arg1.Type->Ident.c_str());
		break;
		case UnitActionPatrol:
			file->printf(", \"patrol\", {%d, %d}",
				order->Arg1.Patrol.x, order->Arg1.Patrol.y);
			break;
		case UnitActionSpellCast:
			if (order->Arg1.Spell) {
				file->printf(", \"spell\", \"%s\"", order->Arg1.Spell->Ident.c_str());
			}
			break;
		case UnitActionResearch:
			if (order->Arg1.Upgrade) {
				file->printf(", \"upgrade\", \"%s\"", order->Arg1.Upgrade->Ident.c_str());
			}
			break;
		case UnitActionResource :
		case UnitActionReturnGoods :
			if (order->CurrentResource) {
				file->printf(", \"current-resource\", \"%s\",",
					DefaultResourceNames[order->CurrentResource].c_str());
				if(order->CurrentResource == WoodCost) {
					file->printf(" \"resource-pos\", {%d, %d}",
						order->Arg1.Resource.Pos.x, order->Arg1.Resource.Pos.y);
				} else {
					if (order->Arg1.Resource.Mine->Destroyed) {
						/* this unit is destroyed so it's not in the global unit
						 * array - this means it won't be saved!!! */
						printf ("FIXME: storing destroyed Mine - loading will fail.\n");
					}
					file->printf(" \"resource-mine\", \"%s\"",
						UnitReference(*order->Arg1.Resource.Mine).c_str());
				}
			}
			break;
		default:
			break;
	}

	file->printf("}");
}