예제 #1
0
/**
**  Send unit to harvest resources
**
**  @param unit   pointer to unit.
**  @param dest   destination unit.
**  @param flush  if true, flush command queue.
*/
void CommandResource(CUnit &unit, CUnit &dest, int flush)
{
	if (IsUnitValidForNetwork(unit) == false) {
		return ;
	}
	if (dest.Destroyed) {
		return ;
	}
	if (!unit.Type->Building && !unit.Type->Harvester) {
		ClearSavedAction(unit);
		return ;
	}
	COrderPtr *order;

	if (unit.Type->Building) {
		ClearNewAction(unit);
		order = &unit.NewOrder;
	} else {
		order = GetNextOrder(unit, flush);
		if (order == NULL) {
			return;
		}
	}
	*order = COrder::NewActionResource(unit, dest);
	ClearSavedAction(unit);
}
예제 #2
0
/**
**  Send unit to harvest resources
**
**  @param unit   pointer to unit.
**  @param dest   destination unit.
**  @param flush  if true, flush command queue.
*/
void CommandResource(CUnit *unit, CUnit *dest, int flush)
{
	COrder *order;

	//
	// Check if unit is still valid and Goal still alive? (NETWORK!)
	//
	if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie &&
			!dest->Destroyed) {
		// FIXME: more races, could happen with many orders in queue.
		if (!unit->Type->Building && !unit->Type->Harvester) {
			ClearSavedAction(unit);
			return;
		}

		// FIXME: if low-level supports searching, pass NoUnitP down.

		if (unit->Type->Building) {
			// FIXME: should find a better way for pending orders.
			order = &unit->NewOrder;
			ReleaseOrder(order);
		} else if (!(order = GetNextOrder(unit, flush))) {
			return;
		}
		order->Init();
		order->Action = UnitActionResource;
		order->Goal = dest;
		dest->RefsIncrease();
		order->Range = 1;
	}
	ClearSavedAction(unit);
}
예제 #3
0
/**
**  Let unit returning goods.
**
**  @param unit   pointer to unit.
**  @param goal   bring goods to this depot.
**  @param flush  if true, flush command queue.
*/
void CommandReturnGoods(CUnit *unit, CUnit *goal, int flush)
{
	COrder *order;

	//
	// Check if unit is still valid and Goal still alive? (NETWORK!)
	//
	if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie) {
		// FIXME: more races, could happen with many orders in queue.
		if (!unit->Type->Building && !unit->Type->Harvester && !unit->ResourcesHeld) {
			ClearSavedAction(unit);
			return;
		}

		if (unit->Type->Building) {
			// FIXME: should find a better way for pending orders.
			order = &unit->NewOrder;
			ReleaseOrder(order);
		} else if (!(order = GetNextOrder(unit, flush))) {
			return;
		}
		order->Init();

		order->Action = UnitActionReturnGoods;
		//
		// Destination could be killed. NETWORK!
		//
		if (goal && !goal->Destroyed) {
			order->Goal = goal;
			goal->RefsIncrease();
		}
		order->Range = 1;
	}
	ClearSavedAction(unit);
}
예제 #4
0
파일: command.cpp 프로젝트: meiavy/Wyrmgus
/**
**  Send unit harvest a location
**
**  @param unit   pointer to unit.
**  @param pos    map position for harvest.
**  @param flush  if true, flush command queue.
*/
void CommandResourceLoc(CUnit &unit, const Vec2i &pos, int flush)
{
	if (IsUnitValidForNetwork(unit) == false) {
		return ;
	}
	if (!unit.Type->Building && !unit.Type->BoolFlag[HARVESTER_INDEX].value) {
		ClearSavedAction(unit);
		return ;
	}
	//Wyrmgus start
	CMapField &mf = *Map.Field(unit.tilePos);
	if ((mf.Flags & MapFieldBridge) && !unit.Type->BoolFlag[BRIDGE_INDEX].value && unit.Type->UnitType == UnitTypeLand) { 
		std::vector<CUnit *> table;
		Select(unit.tilePos, unit.tilePos, table);
		for (size_t i = 0; i != table.size(); ++i) {
			if (!table[i]->Removed && table[i]->Type->BoolFlag[BRIDGE_INDEX].value && table[i]->CanMove()) {
				CommandStopUnit(*table[i]); //always stop the raft if a new command is issued
			}
		}
	}
	//Wyrmgus end
	COrderPtr *order;

	if (unit.Type->Building) {
		ClearNewAction(unit);
		order = &unit.NewOrder;
	} else {
		order = GetNextOrder(unit, flush);
		if (order == NULL) {
			return;
		}
	}
	*order = COrder::NewActionResource(unit, pos);
	ClearSavedAction(unit);
}
예제 #5
0
파일: command.cpp 프로젝트: meiavy/Wyrmgus
/**
**  Cast a spell at position or unit.
**
**  @param unit   Pointer to unit.
**  @param pos    map position to spell cast on.
**  @param dest   Spell cast on unit (if exist).
**  @param spell  Spell type pointer.
**  @param flush  If true, flush command queue.
*/
void CommandSpellCast(CUnit &unit, const Vec2i &pos, CUnit *dest, const SpellType &spell, int flush, bool isAutocast)
{
	DebugPrint(": %d casts %s at %d %d on %d\n" _C_
			   UnitNumber(unit) _C_ spell.Ident.c_str() _C_ pos.x _C_ pos.y _C_ dest ? UnitNumber(*dest) : 0);
	Assert(unit.Type->CanCastSpell[spell.Slot]);
	Assert(Map.Info.IsPointOnMap(pos));

	if (IsUnitValidForNetwork(unit) == false) {
		return ;
	}
	//Wyrmgus start
	CMapField &mf = *Map.Field(unit.tilePos);
	if ((mf.Flags & MapFieldBridge) && !unit.Type->BoolFlag[BRIDGE_INDEX].value && unit.Type->UnitType == UnitTypeLand) { 
		std::vector<CUnit *> table;
		Select(unit.tilePos, unit.tilePos, table);
		for (size_t i = 0; i != table.size(); ++i) {
			if (!table[i]->Removed && table[i]->Type->BoolFlag[BRIDGE_INDEX].value && table[i]->CanMove()) {
				CommandStopUnit(*table[i]); //always stop the raft if a new command is issued
			}
		}
	}
	//Wyrmgus end
	COrderPtr *order = GetNextOrder(unit, flush);

	if (order == NULL) {
		return;
	}

	*order = COrder::NewActionSpellCast(spell, pos, dest, true);
	ClearSavedAction(unit);
}
예제 #6
0
/**
**  Building starts training an unit.
**
**  @param unit   pointer to unit.
**  @param type   unit type to train.
**  @param flush  if true, flush command queue.
*/
void CommandTrainUnit(CUnit &unit, CUnitType &type, int)
{
	if (IsUnitValidForNetwork(unit) == false) {
		return ;
	}
	// Check if enough resources remains? (NETWORK!)
	// FIXME: wrong if append to message queue!!!
	if (unit.Player->CheckLimits(type) < 0
		|| unit.Player->CheckUnitType(type)) {
		return;
	}
	// Not already training?
	if (!EnableTrainingQueue && unit.CurrentAction() == UnitActionTrain) {
		DebugPrint("Unit queue disabled!\n");
		return;
	}

	const int noFlushCommands = 0;
	COrderPtr *order = GetNextOrder(unit, noFlushCommands);

	if (order == NULL) {
		return;
	}
	*order = COrder::NewActionTrain(unit, type);
	ClearSavedAction(unit);
}
예제 #7
0
/**
**  Cancel Building researching.
**
**  @param unit  Pointer to unit.
*/
void CommandCancelResearch(CUnit *unit)
{
	ReleaseOrders(unit); // empty command queue

	//
	// Check if unit is still researching? (NETWORK!)
	//
	if (unit->Orders[0]->Action == UnitActionResearch) {
		const CUpgrade *upgrade;

		upgrade = unit->Data.Research.Upgrade;
		unit->Player->UpgradeTimers.Upgrades[upgrade->ID] = 0;

		unit->Player->AddCostsFactor(upgrade->Costs,
			CancelResearchCostsFactor);
		unit->Orders[0]->Init();

		unit->Orders[0]->Action = UnitActionStill;

		unit->SubAction = 0;

		//
		// Update interface.
		//
		if (unit->Player == ThisPlayer && unit->Selected) {
			SelectedUnitChanged();
		}
	}
	ClearSavedAction(unit);
}
예제 #8
0
/**
**  Building starts upgrading to.
**
**  @param unit   pointer to unit.
**  @param type   upgrade to type
**  @param flush  if true, flush command queue.
*/
void CommandUpgradeTo(CUnit *unit, CUnitType *type, int flush)
{
	COrder *order;

	//
	// Check if unit is still valid and Goal still alive? (NETWORK!)
	//
	if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie) {
		//
		// Check if enough resources remains? (NETWORK!)
		//
		if (unit->Player->CheckUnitType(type)) {
			return;
		}

		if (!flush) {
			DebugPrint("FIXME: must support order queing!!");
		}
		if (!(order = GetNextOrder(unit, flush))) {
			return;
		}
		order->Init();

		// FIXME: if you give quick an other order, the resources are lost!
		unit->Player->SubUnitType(type);

		order->Action = UnitActionUpgradeTo;
		order->Type = type;
	}
	ClearSavedAction(unit);
}
예제 #9
0
/**
**  Let an unit patrol from current to new position
**
**  FIXME: want to support patroling between units.
**
**  @param unit   pointer to unit.
**  @param x      X map position to patrol between.
**  @param y      Y map position to patrol between.
**  @param flush  if true, flush command queue.
*/
void CommandPatrolUnit(CUnit *unit, int x, int y, int flush)
{
	COrder *order;

	Assert(x >= 0 && y >= 0 && x < Map.Info.MapWidth && y < Map.Info.MapHeight);

	//
	// Check if unit is still valid? (NETWORK!)
	//
	if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie) {
		if (!CanMove(unit)) {
			// FIXME: should find a better way for pending orders.
			order = &unit->NewOrder;
			ReleaseOrder(order);
		} else if (!(order = GetNextOrder(unit, flush))) {
			return;
		}
		order->Init();

		order->Action = UnitActionPatrol;
		order->X = x;
		order->Y = y;
		Assert(!(unit->X & ~0xFFFF) && !(unit->Y & ~0xFFFF));
		order->Arg1.Patrol.X = unit->X;
		order->Arg1.Patrol.Y = unit->Y;
	}
	ClearSavedAction(unit);
}
예제 #10
0
/**
**  Cancel building upgrading to.
**
**  @param unit  pointer to unit.
*/
void CommandCancelUpgradeTo(CUnit *unit)
{
	ReleaseOrders(unit); // empty command queue

	//
	// Check if unit is still upgrading? (NETWORK!)
	//
	if (unit->Orders[0]->Action == UnitActionUpgradeTo) {

		unit->Player->AddCostsFactor(
			unit->Orders[0]->Type->Stats[unit->Player->Index].Costs,
			CancelUpgradeCostsFactor);

		unit->Orders[0]->Init();

		unit->Orders[0]->Action = UnitActionStill;

		unit->SubAction = 0;

		//
		// Update interface.
		//
		if (unit->Player == ThisPlayer && unit->Selected) {
			SelectedUnitChanged();
		}
	}
	ClearSavedAction(unit);
}
예제 #11
0
/**
**  Attack ground with unit.
**
**  @param unit   pointer to unit.
**  @param x      X map position to fire on.
**  @param y      Y map position to fire on.
**  @param flush  if true, flush command queue.
*/
void CommandAttackGround(CUnit *unit, int x, int y, int flush)
{
	COrder *order;

	Assert(x >= 0 && y >= 0 && x < Map.Info.MapWidth && y < Map.Info.MapHeight);

	//
	// Check if unit is still valid? (NETWORK!)
	//
	if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie) {
		if (unit->Type->Building) {
			// FIXME: should find a better way for pending orders.
			order = &unit->NewOrder;
			ReleaseOrder(order);
		} else if (!(order = GetNextOrder(unit, flush))) {
			return;
		}
		order->Init();

		order->Action = UnitActionAttackGround;
		order->X = x;
		order->Y = y;
		order->Range = unit->Stats->Variables[ATTACKRANGE_INDEX].Max;
		order->MinRange = unit->Type->MinAttackRange;

		DebugPrint("FIXME this next\n");
	}
	ClearSavedAction(unit);
}
예제 #12
0
/**
**  Unload a transporter.
**
**  @param unit   pointer to unit.
**  @param x      X map position to unload.
**  @param y      Y map position to unload.
**  @param what   unit to be unloaded, NoUnitP all.
**  @param flush  if true, flush command queue.
*/
void CommandUnload(CUnit *unit, int x, int y, CUnit *what, int flush)
{
	COrder *order;

	//
	// Check if unit is still valid? (NETWORK!)
	//
	if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie) {
		if (!(order = GetNextOrder(unit, flush))) {
			return;
		}
		order->Init();

		order->Action = UnitActionUnload;
		order->X = x;
		order->Y = y;
		//
		// Destination could be killed.
		// Should be handled in action, but is not possible!
		// Unit::Refs is used as timeout counter.
		//
		if (what && !what->Destroyed) {
			order->Goal = what;
			what->RefsIncrease();
		}
	}
	ClearSavedAction(unit);
}
예제 #13
0
/**
**  Board a transporter with unit.
**
**  @param unit   pointer to unit.
**  @param dest   unit to be boarded.
**  @param flush  if true, flush command queue.
*/
void CommandBoard(CUnit *unit, CUnit *dest, int flush)
{
	COrder *order;

	//
	// Check if unit is still valid? (NETWORK!)
	//
	if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie) {
		//
		// Destination could be killed.
		// Should be handled in action, but is not possible!
		// Unit::Refs is used as timeout counter.
		//
		if (dest->Destroyed) {
			return;
		}

		if (unit->Type->Building) {
			// FIXME: should find a better way for pending orders.
			order = &unit->NewOrder;
			ReleaseOrder(order);
		} else if (!(order = GetNextOrder(unit, flush))) {
			return;
		}
		order->Init();

		order->Action = UnitActionBoard;
		order->Goal = dest;
		dest->RefsIncrease();
		order->Range = 1;
	}
	ClearSavedAction(unit);
}
예제 #14
0
/**
**  Attack with unit at new position
**
**  @param unit    pointer to unit.
**  @param pos     map position to attack.
**  @param target  or unit to be attacked.
**  @param flush   if true, flush command queue.
*/
void CommandAttack(CUnit &unit, const Vec2i &pos, CUnit *target, int flush)
{
	Assert(Map.Info.IsPointOnMap(pos));
	if (IsUnitValidForNetwork(unit) == false) {
		return ;
	}

	COrderPtr *order;

	if (!unit.Type->CanAttack) {
		ClearNewAction(unit);
		order = &unit.NewOrder;
	} else {
		order = GetNextOrder(unit, flush);
		if (order == NULL) {
			return;
		}
	}
	if (target && target->IsAlive()) {
		*order = COrder::NewActionAttack(unit, *target);
	} else {
		*order = COrder::NewActionAttack(unit, pos);
	}
	ClearSavedAction(unit);
}
예제 #15
0
/**
**  Cancel the training of an unit.
**
**  @param unit  pointer to unit.
**  @param slot  slot number to cancel.
**  @param type  Unit-type to cancel.
*/
void CommandCancelTraining(CUnit *unit, int slot, const CUnitType *type)
{
	DebugPrint("Cancel %d type: %s\n" _C_ slot _C_
		type ? type->Ident.c_str() : "-any-");

	ClearSavedAction(unit);

	//
	// Check if unit is still training 'slot'? (NETWORK!)
	//

	if (slot == -1) {
		// Cancel All training
		while (unit->Orders[0]->Action == UnitActionTrain) {
			unit->Player->AddCostsFactor(
				unit->Orders[0]->Type->Stats[unit->Player->Index].Costs,
				CancelTrainingCostsFactor);
			RemoveOrder(unit, 0);
		}
		unit->Data.Train.Ticks = 0;
		if (unit->Player == ThisPlayer && unit->Selected) {
			SelectedUnitChanged();
		}
	} else if (unit->OrderCount <= slot) {
		// Order has moved
		return;
	} else if (unit->Orders[slot]->Action != UnitActionTrain) {
		// Order has moved, we are not training
		return;
	} else if (unit->Orders[slot]->Action == UnitActionTrain) {
		// Still training this order, same unit?
		if (type && unit->Orders[slot]->Type != type) {
			// Different unit being trained
			return;
		}

		DebugPrint("Cancel training\n");

		unit->Player->AddCostsFactor(
			unit->Orders[slot]->Type->Stats[unit->Player->Index].Costs,
			CancelTrainingCostsFactor);

	
		if (!slot) { // Canceled in work slot
			unit->Data.Train.Ticks = 0;
		}
		RemoveOrder(unit, slot);

		//
		// Update interface.
		//
		if (unit->Player == ThisPlayer && unit->Selected) {
			SelectedUnitChanged();
		}
	}
}
예제 #16
0
파일: command.cpp 프로젝트: meiavy/Wyrmgus
/**
**  Stop unit.
**
**  @param unit  pointer to unit.
*/
void CommandStopUnit(CUnit &unit)
{
	// Ignore that the unit could be removed.
	COrderPtr *order = GetNextOrder(unit, FlushCommands); // Flush them.
	Assert(order);
	Assert(*order == NULL);
	*order = COrder::NewActionStill();

	ClearSavedAction(unit);
	ClearNewAction(unit);
}
예제 #17
0
파일: command.cpp 프로젝트: meiavy/Wyrmgus
/**
**  Cancel the building construction, or kill a unit.
**
**  @param unit  pointer to unit.
*/
void CommandDismiss(CUnit &unit)
{
	// Check if building is still under construction? (NETWORK!)
	if (unit.CurrentAction() == UnitActionBuilt) {
		unit.CurrentOrder()->Cancel(unit);
	} else {
		DebugPrint("Suicide unit ... \n");
		LetUnitDie(unit, true);
	}
	ClearSavedAction(unit);
}
예제 #18
0
파일: command.cpp 프로젝트: meiavy/Wyrmgus
/**
**  Cancel Building researching.
**
**  @param unit  Pointer to unit.
*/
void CommandCancelResearch(CUnit &unit)
{
	// Check if unit is still researching? (NETWORK!)
	if (unit.CurrentAction() == UnitActionResearch) {
		unit.CurrentOrder()->Cancel(unit);
		RemoveOrder(unit, 0);
		if (!Selected.empty()) {
			SelectedUnitChanged();
		}
	}
	ClearSavedAction(unit);
}
예제 #19
0
/**
**  Cancel building upgrading to.
**
**  @param unit  pointer to unit.
*/
void CommandCancelUpgradeTo(CUnit &unit)
{
	// Check if unit is still upgrading? (NETWORK!)
	if (unit.CurrentAction() == UnitActionUpgradeTo) {
		unit.CurrentOrder()->Cancel(unit);
		RemoveOrder(unit, 0);
		if (Selected) {
			SelectedUnitChanged();
		}
	}
	ClearSavedAction(unit);
}
예제 #20
0
파일: command.cpp 프로젝트: meiavy/Wyrmgus
/**
**  Unload a transporter.
**
**  @param unit   pointer to unit.
**  @param pos    map position to unload.
**  @param what   unit to be unloaded, NULL for all.
**  @param flush  if true, flush command queue.
*/
void CommandUnload(CUnit &unit, const Vec2i &pos, CUnit *what, int flush)
{
	if (IsUnitValidForNetwork(unit) == false) {
		return ;
	}
	COrderPtr *order = GetNextOrder(unit, flush);

	if (order == NULL) {
		return;
	}
	*order = COrder::NewActionUnload(pos, what);
	ClearSavedAction(unit);
}
예제 #21
0
/**
**  Cancel the building construction, or kill an unit.
**
**  @param unit  pointer to unit.
*/
void CommandDismiss(CUnit *unit)
{
	//
	// Check if building is still under construction? (NETWORK!)
	//
	if (unit->Orders[0]->Action == UnitActionBuilt) {
		unit->Data.Built.Cancel = 1;
	} else {
		DebugPrint("Suicide unit ... \n");
		LetUnitDie(unit);
	}
	ClearSavedAction(unit);
}
예제 #22
0
/**
**  Order an already formed Order structure
**
**  @param unit      pointer to unit
**  @param cpyorder  pointer to valid order
**  @param flush     if true, flush command queue.
*/
void CommandAnyOrder(CUnit *unit, COrder *cpyorder, int flush)
{
	COrder *order;

	if (!(order = GetNextOrder(unit, flush))) {
		return;
	}

	*order = *cpyorder;
	if (order->Goal) {
		order->Goal->RefsIncrease();
	}
	ClearSavedAction(unit);
}
예제 #23
0
/**
**  Attack with unit at new position
**
**  @param unit    pointer to unit.
**  @param x       X map position to attack.
**  @param y       Y map position to attack.
**  @param attack  or unit to be attacked.
**  @param flush   if true, flush command queue.
*/
void CommandAttack(CUnit *unit, int x, int y, CUnit *attack, int flush)
{
	COrder *order;

	Assert(x >= 0 && y >= 0 && x < Map.Info.MapWidth && y < Map.Info.MapHeight);

	//
	// Check if unit is still valid? (NETWORK!)
	//
	if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie) {
		if (!unit->Type->CanAttack) {
			// FIXME: should find a better way for pending orders.
			order = &unit->NewOrder;
			ReleaseOrder(order);
		} else if (!(order = GetNextOrder(unit, flush))) {
			return;
		}
		order->Init();

		order->Action = UnitActionAttack;
		if (attack) {
			//
			// Destination could be killed.
			// Should be handled in action, but is not possible!
			// Unit::Refs is used as timeout counter.
			//
			if (attack->Destroyed) {
				order->X = attack->X + attack->Type->TileWidth / 2;
				order->Y = attack->Y + attack->Type->TileHeight / 2;
			} else {
				// Removed, Dying handled by action routine.
				order->Goal = attack;
				attack->RefsIncrease();
				order->Range = unit->Stats->Variables[ATTACKRANGE_INDEX].Max;
				order->MinRange = unit->Type->MinAttackRange;
			}
		} else if (Map.WallOnMap(x,y)) {
			// FIXME: look into action_attack.c about this ugly problem
			order->X = x;
			order->Y = y;
			order->Range = unit->Stats->Variables[ATTACKRANGE_INDEX].Max;
			order->MinRange = unit->Type->MinAttackRange;
		} else {
			order->X = x;
			order->Y = y;
		}
	}
	ClearSavedAction(unit);
}
예제 #24
0
파일: command.cpp 프로젝트: meiavy/Wyrmgus
/**
**  Let unit returning goods.
**
**  @param unit   pointer to unit.
**  @param depot  bring goods to this depot.
**  @param flush  if true, flush command queue.
*/
void CommandReturnGoods(CUnit &unit, CUnit *depot, int flush)
{
	if (IsUnitValidForNetwork(unit) == false) {
		return ;
	}
	if ((unit.Type->BoolFlag[HARVESTER_INDEX].value && unit.ResourcesHeld == 0)
		|| (!unit.Type->Building && !unit.Type->BoolFlag[HARVESTER_INDEX].value)) {
		ClearSavedAction(unit);
		return ;
	}
	COrderPtr *order;

	if (unit.Type->Building) {
		ClearNewAction(unit);
		order = &unit.NewOrder;
	} else {
		order = GetNextOrder(unit, flush);
		if (order == NULL) {
			return;
		}
	}
	*order = COrder::NewActionReturnGoods(unit, depot);
	ClearSavedAction(unit);
}
예제 #25
0
/**
**  Cast a spell at position or unit.
**
**  @param unit   Pointer to unit.
**  @param x      X map position to spell cast on.
**  @param y      Y map position to spell cast on.
**  @param dest   Spell cast on unit (if exist).
**  @param spell  Spell type pointer.
**  @param flush  If true, flush command queue.
*/
void CommandSpellCast(CUnit *unit, int x, int y, CUnit *dest,
	SpellType *spell, int flush)
{
	COrder *order;

	Assert(x >= 0 && y >= 0 && x < Map.Info.MapWidth && y < Map.Info.MapHeight);

	DebugPrint(": %d casts %s at %d %d on %d\n" _C_
		UnitNumber(unit) _C_ spell->Ident.c_str() _C_ x _C_ y _C_ dest ? UnitNumber(dest) : 0);
	Assert(unit->Type->CanCastSpell[spell->Slot]);

	//
	// Check if unit is still valid? (NETWORK!)
	//
	if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie) {
		// FIXME: should I check here, if there is still enough mana?

		if (!(order = GetNextOrder(unit, flush))) {
			return;
		}
		order->Init();

		order->Action = UnitActionSpellCast;
		order->Range = spell->Range;
		if (dest) {
			//
			// Destination could be killed.
			// Should be handled in action, but is not possible!
			// Unit::Refs is used as timeout counter.
			//
			if (dest->Destroyed) {
				// FIXME: where check if spell needs an unit as destination?
				// FIXME: dest->Type is now set to 0. maybe we shouldn't bother.
				order->X = dest->X /*+ dest->Type->TileWidth / 2*/  - order->Range;
				order->Y = dest->Y /*+ dest->Type->TileHeight / 2*/ - order->Range;
				order->Range <<= 1;
			} else {
				order->Goal = dest;
				dest->RefsIncrease();
			}
		} else {
			order->X = x;
			order->Y = y;
		}
		order->Arg1.Spell = spell;
	}
	ClearSavedAction(unit);
}
예제 #26
0
파일: command.cpp 프로젝트: meiavy/Wyrmgus
/**
**  Stand ground.
**
**  @param unit   pointer to unit.
**  @param flush  if true, flush command queue.
*/
void CommandStandGround(CUnit &unit, int flush)
{
	COrderPtr *order;

	if (unit.Type->Building) {
		ClearNewAction(unit);
		order = &unit.NewOrder;
	} else {
		order = GetNextOrder(unit, flush);
		if (order == NULL) {
			return;
		}
	}
	*order = COrder::NewActionStandGround();
	ClearSavedAction(unit);
}
예제 #27
0
/**
**  Building starts researching.
**
**  @param unit   pointer to unit.
**  @param what   what to research.
**  @param flush  if true, flush command queue.
*/
void CommandResearch(CUnit &unit, CUpgrade &what, int flush)
{
	if (IsUnitValidForNetwork(unit) == false) {
		return ;
	}
	// Check if enough resources remains? (NETWORK!)
	if (unit.Player->CheckCosts(what.Costs)) {
		return;
	}
	COrderPtr *order = GetNextOrder(unit, flush);
	if (order == NULL) {
		return;
	}
	*order = COrder::NewActionResearch(unit, what);
	ClearSavedAction(unit);
}
예제 #28
0
/**
**  Stand ground.
**
**  @param unit   pointer to unit.
**  @param flush  if true, flush command queue.
*/
void CommandStandGround(CUnit *unit, int flush)
{
	COrder *order;

	// Ignore that the unit could be removed.

	if (unit->Type->Building) {
		// FIXME: should find a better way for pending orders.
		order = &unit->NewOrder;
		ReleaseOrder(order);
	} else if (!(order = GetNextOrder(unit, flush))) {
		return;
	}
	order->Init();
	order->Action = UnitActionStandGround;
	ClearSavedAction(unit);
}
예제 #29
0
/**
**  Send unit harvest a location
**
**  @param unit   pointer to unit.
**  @param x      X map position for harvest.
**  @param y      Y map position for harvest.
**  @param flush  if true, flush command queue.
*/
void CommandResourceLoc(CUnit *unit, int x, int y, int flush)
{
	COrder *order;
	int nx;
	int ny;

	//
	// Check if unit is still valid? (NETWORK!)
	//
	if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie) {
		if (unit->Type->Building) {
			// FIXME: should find a better way for pending orders.
			order = &unit->NewOrder;
			ReleaseOrder(order);
		} else if (!(order = GetNextOrder(unit, flush))) {
			return;
		}
		order->Init();

		order->Action = UnitActionResource;

		//  Find the closest piece of wood next to a tile where the unit can move
		if (!FindTerrainType(0, (unit->Type->MovementMask), 1, 20,
				unit->Player, x, y, &nx, &ny)) {
			DebugPrint("FIXME: Give up???\n");
		}

		// Max Value > 1
		if ((abs(nx - x) | abs(ny - y)) > 1) {
			if (!FindTerrainType(0, MapFieldForest, 0, 20, unit->Player,
					nx, ny, &nx, &ny)) {
				DebugPrint("FIXME: Give up???\n");
			}
		} else {
			// The destination is next to a reacahble tile.
			nx = x;
			ny = y;
		}
		order->X = nx;
		order->Y = ny;

		order->Range = 1;
	}
	ClearSavedAction(unit);
}
예제 #30
0
/**
**  Building starts researching.
**
**  @param unit   pointer to unit.
**  @param what   what to research.
**  @param flush  if true, flush command queue.
*/
void CommandResearch(CUnit *unit, CUpgrade *what, int flush)
{
	COrder *order;

	//
	// Check if unit is still valid and Goal still alive? (NETWORK!)
	//
	if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie) {
		//
		// Check if enough resources remains? (NETWORK!)
		//
		if (unit->Player->CheckCosts(what->Costs)) {
			return;
		}

		if (!flush) {
			DebugPrint("FIXME: must support order queing!!");
		} else {
			if (unit->Orders[0]->Action == UnitActionResearch) {
				const CUpgrade *upgrade;

				// Cancel current research
				upgrade = unit->Data.Research.Upgrade;
				unit->Player->UpgradeTimers.Upgrades[upgrade->ID] = 0;
				unit->Player->AddCostsFactor(upgrade->Costs,
					CancelResearchCostsFactor);
				unit->SubAction = 0;
			}
		}

		if (!(order = GetNextOrder(unit, flush))) {
			return;
		}
		order->Init();

		// FIXME: if you give quick an other order, the resources are lost!
		unit->Player->SubCosts(what->Costs);

		order->Action = UnitActionResearch;
		order->X = order->Y = -1;
		order->Arg1.Upgrade = what;
	}
	ClearSavedAction(unit);
}