Beispiel #1
0
int FindAndSortUnits(const CViewport *vp, CUnitDrawProxy table[])
{
	CUnit* buffer[UnitMax];

	//
	//  Select all units touching the viewpoint.
	//
	int n = Map.Select(vp->MapX - 1, vp->MapY - 1, vp->MapX + vp->MapWidth + 1,
		vp->MapY + vp->MapHeight + 1, buffer);

	for (int i = 0; i < n; ++i) {
		if (!buffer[i]->IsVisibleInViewport(vp) ||
			 buffer[i]->Destroyed || buffer[i]->Container ||
			 buffer[i]->Type->Revealer) {
			buffer[i--] = buffer[--n];
		}
	}

	if (n > 1) {
		std::sort(buffer, buffer + n, DrawLevelCompare);
		for (int i = 0; i < n; ++i) {
			UpdateUnitVariables(*buffer[i]);
			table[i] = buffer[i];
		}
	} else if (n == 1) {
		UpdateUnitVariables(*buffer[0]);
		table[0] = buffer[0];
	}

	return n;
}
Beispiel #2
0
/**
**  Calculate damage.
**
**  @param attacker  Attacker.
**  @param goal      Goal unit.
**
**  @return          damage produces on goal.
*/
static int CalculateDamage(const CUnit &attacker, const CUnit &goal)
{
	if (!Damage) { // Use old method.
		return CalculateDamageStats(*attacker.Stats, *goal.Stats,
									attacker.Variable[BLOODLUST_INDEX].Value);
	}
	Assert(Damage);

	UpdateUnitVariables(const_cast<CUnit &>(attacker));
	UpdateUnitVariables(const_cast<CUnit &>(goal));
	TriggerData.Attacker = const_cast<CUnit *>(&attacker);
	TriggerData.Defender = const_cast<CUnit *>(&goal);
	const int res = EvalNumber(Damage);
	TriggerData.Attacker = NULL;
	TriggerData.Defender = NULL;
	return res;
}
/**
**  Draw decoration (invis, for the unit.)
**
**  @param unit       Pointer to the unit.
**  @param type       Type of the unit.
**  @param screenPos  Screen position of the unit.
*/
static void DrawDecoration(const CUnit &unit, const CUnitType &type, const PixelPos &screenPos)
{
	int x = screenPos.x;
	int y = screenPos.y;
#ifdef DEBUG
	// Show the number of references.
	CLabel(GetGameFont()).DrawClip(x + 1, y + 1, unit.Refs);
#endif

	UpdateUnitVariables(const_cast<CUnit &>(unit));
	// Now show decoration for each variable.
	for (std::vector<CDecoVar *>::const_iterator i = UnitTypeVar.DecoVar.begin();
		 i < UnitTypeVar.DecoVar.end(); ++i) {
		const CDecoVar &var = *(*i);
		const int value = unit.Variable[var.Index].Value;
		const int max = unit.Variable[var.Index].Max;
		Assert(value <= max);

		if (!((value == 0 && !var.ShowWhenNull) || (value == max && !var.ShowWhenMax)
			  || (var.HideHalf && value != 0 && value != max)
			  || (!var.ShowIfNotEnable && !unit.Variable[var.Index].Enable)
			  || (var.ShowOnlySelected && !unit.Selected)
			  || (unit.Player->Type == PlayerNeutral && var.HideNeutral)
			  || (ThisPlayer->IsEnemy(unit) && !var.ShowOpponent)
			  || (ThisPlayer->IsAllied(unit) && (unit.Player != ThisPlayer) && var.HideAllied)
			  || max == 0)) {
			var.Draw(
				x + var.OffsetX + var.OffsetXPercent * unit.Type->TileWidth * PixelTileSize.x / 100,
				y + var.OffsetY + var.OffsetYPercent * unit.Type->TileHeight * PixelTileSize.y / 100,
				type, unit.Variable[var.Index]);
		}
	}

	// Draw group number
	if (unit.Selected && unit.GroupId != 0
#ifndef DEBUG
		&& unit.Player == ThisPlayer
#endif
	   ) {
		int groupId = 0;

		if (unit.Player->AiEnabled) {
			groupId = unit.GroupId - 1;
		} else {
			for (groupId = 0; !(unit.GroupId & (1 << groupId)); ++groupId) {
			}
		}
		const int width = GetGameFont().Width(groupId);
		x += (unit.Type->TileWidth * PixelTileSize.x + unit.Type->BoxWidth) / 2 - width;
		const int height = GetGameFont().Height();
		y += (unit.Type->TileHeight * PixelTileSize.y + unit.Type->BoxHeight) / 2 - height;
		CLabel(GetGameFont()).DrawClip(x, y, groupId);
	}
}
Beispiel #4
0
/**
**  Calculate damage.
**
**  @param attacker  Attacker.
**  @param goal      Goal unit.
**  @param formula   Formula used to calculate damage.
**
**  @return          damage produces on goal.
*/
int CalculateDamage(const CUnit &attacker, const CUnit &goal, const NumberDesc *formula)
{
	if (!formula) { // Use old method.
		//Wyrmgus start
//		return CalculateDamageStats(*attacker.Stats, *goal.Stats,
//									attacker.Variable[BLOODLUST_INDEX].Value);
		return CalculateDamageStats(attacker, *goal.Stats, &goal);
		//Wyrmgus end
	}
	Assert(formula);

	UpdateUnitVariables(const_cast<CUnit &>(attacker));
	UpdateUnitVariables(const_cast<CUnit &>(goal));
	TriggerData.Attacker = const_cast<CUnit *>(&attacker);
	TriggerData.Defender = const_cast<CUnit *>(&goal);
	const int res = EvalNumber(formula);
	TriggerData.Attacker = NULL;
	TriggerData.Defender = NULL;
	return res;
}
Beispiel #5
0
/**
**  Draw decoration (invis, for the unit.)
**
**  @param unit  Pointer to the unit.
**  @param type  Type of the unit.
**  @param x     Screen X position of the unit.
**  @param y     Screen Y position of the unit.
*/
static void DrawDecoration(const CUnit *unit, const CUnitType *type, int x, int y)
{
#ifdef REFS_DEBUG
	//
	// Show the number of references.
	//
	VideoDrawNumberClip(x + 1, y + 1, GameFont, unit->Refs);
#endif

	UpdateUnitVariables(unit);
	// Now show decoration for each variable.
	for (std::vector<CDecoVar *>::const_iterator i = UnitTypeVar.DecoVar.begin();
		i < UnitTypeVar.DecoVar.end(); ++i) {
		int value;
		int max;

		value = unit->Variable[(*i)->Index].Value;
		max = unit->Variable[(*i)->Index].Max;
		Assert(value <= max);

		if (!((value == 0 && !(*i)->ShowWhenNull) || (value == max && !(*i)->ShowWhenMax) ||
				((*i)->HideHalf && value != 0 && value != max) ||
				(!(*i)->ShowIfNotEnable && !unit->Variable[(*i)->Index].Enable) ||
				((*i)->ShowOnlySelected && !unit->Selected) ||
				(unit->Player->Type == PlayerNeutral && (*i)->HideNeutral) ||
				(ThisPlayer->IsEnemy(unit) && !(*i)->ShowOpponent) ||
				(ThisPlayer->IsAllied(unit) && (unit->Player != ThisPlayer) && (*i)->HideAllied) ||
				max == 0)) {
			(*i)->Draw(
				x + (*i)->OffsetX + (*i)->OffsetXPercent * unit->Type->TileWidth * TileSizeX / 100,
				y + (*i)->OffsetY + (*i)->OffsetYPercent * unit->Type->TileHeight * TileSizeY / 100,
				unit);
		}
	}
	//
	// Draw group number
	//
	if (unit->Selected && unit->GroupId != 0) {
		char buf[2];
		int num;
		int f;

		for (num = 0; !(unit->GroupId & (1 << num)); ++num) {
			;
		}
		buf[0] = num + '0';
		buf[1] = '\0';
		f = GameFont->Width(buf);
		x += (type->TileWidth * TileSizeX + type->BoxWidth) / 2 - f;
		f = GameFont->Height();
		y += (type->TileHeight * TileSizeY + type->BoxHeight) / 2 - f;
		VideoDrawNumberClip(x, y, GameFont, num);
	}
}
Beispiel #6
0
/**
**  Draw decoration (invis, for the unit.)
**
**  @param unit  Pointer to the unit.
**  @param type  Type of the unit.
**  @param x     Screen X position of the unit.
**  @param y     Screen Y position of the unit.
*/
static void DrawDecoration(const CUnit &unit, const CUnitType *type, int x, int y)
{
#ifdef REFS_DEBUG
	//
	// Show the number of references.
	//
	VideoDrawNumberClip(x + 1, y + 1, GameFont, unit.Refs);
#endif

	UpdateUnitVariables(unit);
	// Now show decoration for each variable.
	for (std::vector<CDecoVar *>::const_iterator i = UnitTypeVar.DecoVar.begin();
			i < UnitTypeVar.DecoVar.end(); ++i) {
		int value;
		int max;
		const CDecoVar *var = (*i);
		value = unit.Variable[var->Index].Value;
		max = unit.Variable[var->Index].Max;
		Assert(value <= max);

		if (!((value == 0 && !var->ShowWhenNull) || (value == max && !var->ShowWhenMax) ||
				(var->HideHalf && value != 0 && value != max) ||
				(!var->ShowIfNotEnable && !unit.Variable[var->Index].Enable) ||
				(var->ShowOnlySelected && !unit.Selected) ||
				(unit.Player->Type == PlayerNeutral && var->HideNeutral) ||
				(ThisPlayer->IsEnemy(unit) && !var->ShowOpponent) ||
				(ThisPlayer->IsAllied(unit) && (unit.Player != ThisPlayer) && var->HideAllied) ||
				max == 0)) {
			var->Draw(
				x + var->OffsetX + var->OffsetXPercent * unit.Type->TileWidth * TileSizeX / 100,
				y + var->OffsetY + var->OffsetYPercent * unit.Type->TileHeight * TileSizeY / 100,
				type, unit.Variable[var->Index]);
		}
	}

	//
	// Draw group number
	//
	if (unit.Selected && unit.GroupId != 0
#ifndef DEBUG
		&& unit.Player == ThisPlayer
#endif
		) {
		int groupId = 0;
		for (groupId = 0; !(unit.GroupId & (1 << groupId)); ++groupId)
			;
		int width = GameFont->Width(groupId);
		x += (unit.Type->TileWidth * TileSizeX + unit.Type->BoxWidth) / 2 - width;
		width = GameFont->Height();
		y += (unit.Type->TileHeight * TileSizeY + unit.Type->BoxHeight) / 2 - width;
		CLabel(GameFont).DrawClip(x, y, groupId);
	}
}
Beispiel #7
0
/**
**  Draw the unit info into top-panel.
**
**  @param unit  Pointer to unit.
*/
static void DrawUnitInfo(CUnit &unit)
{
	UpdateUnitVariables(unit);
	
	for (size_t i = 0; i != UI.InfoPanelContents.size(); ++i) {
		if (CanShowContent(UI.InfoPanelContents[i]->Condition, unit)) {
			for (std::vector<CContentType *>::const_iterator content = UI.InfoPanelContents[i]->Contents.begin();
				 content != UI.InfoPanelContents[i]->Contents.end(); ++content) {
				if (CanShowContent((*content)->Condition, unit)) {
					(*content)->Draw(unit, UI.InfoPanelContents[i]->DefaultFont);
				}
			}
		}
	}

	const CUnitType &type = *unit.Type;
	Assert(&type);

	// Draw IconUnit
	DrawUnitInfo_portrait(unit);

	//Wyrmgus start
//	if (unit.Player != ThisPlayer && !ThisPlayer->IsAllied(*unit.Player)) {
	if (unit.Player != ThisPlayer && !ThisPlayer->IsAllied(*unit.Player) && unit.Player->Type != PlayerNeutral) {
	//Wyrmgus end
		return;
	}

	//  Show progress if they are selected.
	if (IsOnlySelected(unit)) {
		if (DrawUnitInfo_single_selection(unit)) {
			return;
		}
	}

	//  Transporting units.
	if (type.CanTransport() && unit.BoardCount && CurrentButtonLevel == unit.Type->ButtonLevelForTransporter) {
		DrawUnitInfo_transporter(unit);
		return;
	}
	
	//Wyrmgus start
	if (unit.HasInventory() && unit.InsideCount && CurrentButtonLevel == unit.Type->ButtonLevelForInventory) {
		DrawUnitInfo_inventory(unit);
		return;
	}
	//Wyrmgus end
}
Beispiel #8
0
/**
**  Draw the unit info into top-panel.
**
**  @param unit  Pointer to unit.
*/
static void DrawUnitInfo(CUnit *unit)
{
	int i;
	CUnitType *type;
	const CUnitStats *stats;
	int x;
	int y;
	CUnit *uins;

	Assert(unit);
	UpdateUnitVariables(unit);
	for (i = 0; i < (int)UI.InfoPanelContents.size(); ++i) {
		if (CanShowContent(UI.InfoPanelContents[i]->Condition, unit)) {
			for (std::vector<CContentType *>::const_iterator content = UI.InfoPanelContents[i]->Contents.begin();
					content != UI.InfoPanelContents[i]->Contents.end(); ++content) {
				if (CanShowContent((*content)->Condition, unit)) {
					(*content)->Draw(unit, UI.InfoPanelContents[i]->DefaultFont);
				}
			}
		}
	}

	type = unit->Type;
	stats = unit->Stats;
	Assert(type);
	Assert(stats);

	// Draw IconUnit
#ifdef USE_MNG
	if (type->Portrait.Num) {
		type->Portrait.Mngs[type->Portrait.CurrMng]->Draw(
			UI.SingleSelectedButton->X, UI.SingleSelectedButton->Y);
		if (type->Portrait.Mngs[type->Portrait.CurrMng]->iteration == type->Portrait.NumIterations) {
			type->Portrait.Mngs[type->Portrait.CurrMng]->Reset();
			// FIXME: should be configurable
			if (type->Portrait.CurrMng == 0) {
				type->Portrait.CurrMng = (SyncRand() % (type->Portrait.Num - 1)) + 1;
				type->Portrait.NumIterations = 1;
			} else {
				type->Portrait.CurrMng = 0;
				type->Portrait.NumIterations = SyncRand() % 16 + 1;
			}
		}
	} else
#endif
	if (UI.SingleSelectedButton) {
		x = UI.SingleSelectedButton->X;
		y = UI.SingleSelectedButton->Y;
		type->Icon.Icon->DrawUnitIcon(unit->Player, UI.SingleSelectedButton->Style,
			(ButtonAreaUnderCursor == ButtonAreaSelected && ButtonUnderCursor == 0) ?
				(IconActive | (MouseButtons & LeftButton)) : 0,
			x, y, "");
	}

	x = UI.InfoPanel.X;
	y = UI.InfoPanel.Y;

	//
	//  Show progress if they are selected.
	//
	if (NumSelected == 1 && Selected[0] == unit) {
		//
		//  Building training units.
		//
		if (unit->Orders[0]->Action == UnitActionTrain) {
			if (unit->OrderCount == 1 || unit->Orders[1]->Action != UnitActionTrain) {
				if (!UI.SingleTrainingText.empty()) {
					VideoDrawText(UI.SingleTrainingTextX, UI.SingleTrainingTextY,
						UI.SingleTrainingFont, UI.SingleTrainingText);
				}
				if (UI.SingleTrainingButton) {
					unit->Orders[0]->Type->Icon.Icon->DrawUnitIcon(unit->Player,
						UI.SingleTrainingButton->Style,
						(ButtonAreaUnderCursor == ButtonAreaTraining &&
							ButtonUnderCursor == 0) ?
							(IconActive | (MouseButtons & LeftButton)) : 0,
						UI.SingleTrainingButton->X, UI.SingleTrainingButton->Y, "");
				}
			} else {
				if (!UI.TrainingText.empty()) {
					VideoDrawTextCentered(UI.TrainingTextX, UI.TrainingTextY,
						UI.TrainingFont, UI.TrainingText);
				}
				if (!UI.TrainingButtons.empty()) {
					for (i = 0; i < unit->OrderCount &&
							i < (int)UI.TrainingButtons.size(); ++i) {
						if (unit->Orders[i]->Action == UnitActionTrain) {
							unit->Orders[i]->Type->Icon.Icon->DrawUnitIcon(unit->Player,
								 UI.TrainingButtons[i].Style,
								(ButtonAreaUnderCursor == ButtonAreaTraining &&
									ButtonUnderCursor == i) ?
									(IconActive | (MouseButtons & LeftButton)) : 0,
								UI.TrainingButtons[i].X, UI.TrainingButtons[i].Y, "");
						}
					}
				}
			}
			return;
		}

		//
		//  Building upgrading to better type.
		//
		if (unit->Orders[0]->Action == UnitActionUpgradeTo) {
			if (UI.UpgradingButton) {
				unit->Orders[0]->Type->Icon.Icon->DrawUnitIcon(unit->Player,
					UI.UpgradingButton->Style,
					(ButtonAreaUnderCursor == ButtonAreaUpgrading &&
						ButtonUnderCursor == 0) ?
						(IconActive | (MouseButtons & LeftButton)) : 0,
					UI.UpgradingButton->X, UI.UpgradingButton->Y, "");
			}
			return;
		}

		//
		//  Building research new technology.
		//
		if (unit->Orders[0]->Action == UnitActionResearch) {
			if (UI.ResearchingButton) {
				unit->Data.Research.Upgrade->Icon->DrawUnitIcon(unit->Player,
					UI.ResearchingButton->Style,
					(ButtonAreaUnderCursor == ButtonAreaResearching &&
						ButtonUnderCursor == 0) ?
						(IconActive | (MouseButtons & LeftButton)) : 0,
					UI.ResearchingButton->X, UI.ResearchingButton->Y, "");
			}
			return;
		}
	}

	//
	//  Transporting units.
	//
	if (type->CanTransport && unit->BoardCount) {
		int j;

		uins = unit->UnitInside;
		for (i = j = 0; i < unit->InsideCount; ++i, uins = uins->NextContained) {
			if (uins->Boarded && j < (int)UI.TransportingButtons.size()) {
				uins->Type->Icon.Icon->DrawUnitIcon(unit->Player, UI.TransportingButtons[j].Style,
					(ButtonAreaUnderCursor == ButtonAreaTransporting && ButtonUnderCursor == j) ?
						(IconActive | (MouseButtons & LeftButton)) : 0,
					UI.TransportingButtons[j].X, UI.TransportingButtons[j].Y, "");
				UiDrawLifeBar(uins, UI.TransportingButtons[j].X, UI.TransportingButtons[j].Y);
				if (uins->Type->CanCastSpell && uins->Variable[MANA_INDEX].Max) {
					UiDrawManaBar(uins, UI.TransportingButtons[j].X, UI.TransportingButtons[j].Y);
				}
				if (ButtonAreaUnderCursor == ButtonAreaTransporting && ButtonUnderCursor == j) {
					UI.StatusLine.Set(uins->Type->Name);
				}
				++j;
			}
		}
		return;
	}
}
Beispiel #9
0
/**
**  Draw the unit info in the info panel.
**  Called when a single unit is selected or the mouse hovers over a unit.
**
**  @param unit  Pointer to unit.
*/
static void DrawUnitInfo(CUnit *unit)
{
	int x = UI.InfoPanel.X;
	int y = UI.InfoPanel.Y;
	bool isEnemy = unit->IsEnemy(ThisPlayer);
	bool isNeutral = (unit->Player->Type == PlayerNeutral);

	UpdateUnitVariables(unit);

	// Draw icon and life bar
	if (UI.SingleSelectedButton) {
		CUIButton *button = UI.SingleSelectedButton;
		bool mouseOver = (ButtonAreaUnderCursor == ButtonAreaSelected && ButtonUnderCursor == 0);

		unit->Type->Icon.Icon->DrawUnitIcon(unit->Player, button->Style,
			mouseOver ? (IconActive | (MouseButtons & LeftButton)) : 0,
			button->X, button->Y, "");
		if (!isNeutral) {
			UiDrawLifeBar(unit, button->X, button->Y);
		}
	}

	// Unit type name
	VideoDrawTextCentered(x + 114, y + 25, GameFont, unit->Type->Name);

	// Hit points
	if (!isEnemy && !isNeutral) {
		std::ostringstream os;
		os << unit->Variable[HP_INDEX].Value << "/" << unit->Variable[HP_INDEX].Max;
		VideoDrawTextCentered(x + 38, y + 62, SmallFont, os.str());
	}

	// Resource amount
	if (unit->Type->CanHarvestFrom && isNeutral) {
		std::string resourceName;
		int amount = 0;

		for (int i = 0; i < MaxCosts; ++i) {
			if (unit->ResourcesHeld[i] != 0) {
				resourceName = _(DefaultDisplayResourceNames[i].c_str());
				amount = unit->ResourcesHeld[i] / CYCLES_PER_SECOND;
				break;
			}
		}

		std::ostringstream os;
		os << resourceName << ": " << amount;
		VideoDrawTextCentered(x + 76, y + 86, GameFont, os.str());
	}

	//
	//  Show extra info if only one unit is selected.
	//
	if (NumSelected == 1 && Selected[0] == unit) {
		// Training units.
		if (!isEnemy && unit->Orders[0]->Action == UnitActionTrain) {
			DrawTrainingUnits(unit);
			return;
		}

		// Transporting units.
		if (!isEnemy && unit->Type->CanTransport && unit->BoardCount) {
			DrawTransportingUnits(unit);
			return;
		}

		// My unit stats
		if (!isEnemy && !isNeutral &&
				unit->Orders[0]->Action != UnitActionBuilt) {
			DrawUnitStats(unit);
		}
	}
}
Beispiel #10
0
/**
**  Gather the resource
**
**  @param unit  Pointer to unit.
**
**  @return      non-zero if ready, otherwise zero.
*/
int COrder_Resource::GatherResource(CUnit &unit)
{
	CUnit *source = 0;
	const ResourceInfo &resinfo = *unit.Type->ResInfo[this->CurrentResource];
	int addload;

	//Wyrmgus start
	bool harvest_from_outside = (this->GetGoal() && this->GetGoal()->Type->BoolFlag[HARVESTFROMOUTSIDE_INDEX].value);
//	if (resinfo.HarvestFromOutside || resinfo.TerrainHarvester) {
	if (harvest_from_outside || Map.Info.IsPointOnMap(this->goalPos)) {
	//Wyrmgus end
		AnimateActionHarvest(unit);
	} else {
		unit.Anim.CurrAnim = NULL;
	}

	this->TimeToHarvest--;

	if (this->DoneHarvesting) {
		//Wyrmgus start
//		Assert(resinfo.HarvestFromOutside || resinfo.TerrainHarvester);
		Assert(harvest_from_outside || Map.Info.IsPointOnMap(this->goalPos));
		//Wyrmgus end
		return !unit.Anim.Unbreakable;
	}

	// Target gone?
	//Wyrmgus start
//	if (resinfo.TerrainHarvester && !Map.Field(this->goalPos)->IsTerrainResourceOnMap(this->CurrentResource)) {
	if (Map.Info.IsPointOnMap(this->goalPos) && !Map.Field(this->goalPos)->IsTerrainResourceOnMap(this->CurrentResource)) {
	//Wyrmgus end
		if (!unit.Anim.Unbreakable) {
			// Action now breakable, move to resource again.
			this->State = SUB_MOVE_TO_RESOURCE;
			// Give it some reasonable look while searching.
			// FIXME: which frame?
			unit.Frame = 0;
		}
		return 0;
		// No wood? Freeze!!!
	}

	while (!this->DoneHarvesting && this->TimeToHarvest < 0) {
		//FIXME: rb - how should it look for WaitAtResource == 0
		if (resinfo.WaitAtResource) {
			// Wyrmgus start
//			this->TimeToHarvest += std::max<int>(1, resinfo.WaitAtResource * SPEEDUP_FACTOR / unit.Player->SpeedResourcesHarvest[resinfo.ResourceId]);
			int wait_at_resource = resinfo.WaitAtResource;
			int resource_harvest_speed = unit.Player->SpeedResourcesHarvest[resinfo.ResourceId];
			if (!Map.Info.IsPointOnMap(this->goalPos) && !harvest_from_outside) {
				wait_at_resource = resinfo.WaitAtResource * 100 / resinfo.ResourceStep;
			}
			if (this->GetGoal()) {
				resource_harvest_speed += this->GetGoal()->Variable[TIMEEFFICIENCYBONUS_INDEX].Value;
			}
			this->TimeToHarvest += std::max<int>(1, wait_at_resource * SPEEDUP_FACTOR / resource_harvest_speed);
			//Wyrmgus end
		} else {
			this->TimeToHarvest += 1;
		}

		// Calculate how much we can load.
		//Wyrmgus start
//		if (resinfo.ResourceStep) {
		if (resinfo.ResourceStep && (harvest_from_outside || Map.Info.IsPointOnMap(this->goalPos))) {
		//Wyrmgus end
			addload = resinfo.ResourceStep;
		} else {
			addload = resinfo.ResourceCapacity;
		}
		// Make sure we don't bite more than we can chew.
		if (unit.ResourcesHeld + addload > resinfo.ResourceCapacity) {
			addload = resinfo.ResourceCapacity - unit.ResourcesHeld;
		}

		//Wyrmgus start
//		if (resinfo.TerrainHarvester) {
		if (Map.Info.IsPointOnMap(this->goalPos)) {
		//Wyrmgus end
			//Wyrmgus start
			CMapField &mf = *Map.Field(this->goalPos);
			if (addload > mf.Value) {
				addload = mf.Value;
			}
			mf.Value -= addload;
			//Wyrmgus end
			unit.ResourcesHeld += addload;

			//Wyrmgus start
//			if (addload && unit.ResourcesHeld == resinfo.ResourceCapacity) {
			if (mf.Value <= 0) {
			//Wyrmgus end
				//Wyrmgus start
//				Map.ClearWoodTile(this->goalPos);
				if (this->CurrentResource == WoodCost) {
					Map.ClearWoodTile(this->goalPos);
				} else if (this->CurrentResource == StoneCost) {
					Map.ClearRockTile(this->goalPos);
				}
				//Wyrmgus end
			}
		} else {
			//Wyrmgus start
//			if (resinfo.HarvestFromOutside) {
			if (harvest_from_outside) {
			//Wyrmgus end
				source = this->GetGoal();
			} else {
				source = unit.Container;
			}

			Assert(source);
			Assert(source->ResourcesHeld <= 655350);
			//Wyrmgus start
			UpdateUnitVariables(*source); //update resource source's variables
			//Wyrmgus end
			bool is_visible = source->IsVisibleAsGoal(*unit.Player);
			// Target is not dead, getting resources.
			if (is_visible) {
				// Don't load more that there is.
				addload = std::min(source->ResourcesHeld, addload);
				unit.ResourcesHeld += addload;
				source->ResourcesHeld -= addload;
			}

			// End of resource: destroy the resource.
			// FIXME: implement depleted resources.
			if ((!is_visible) || (source->ResourcesHeld == 0)) {
				if (unit.Anim.Unbreakable) {
					return 0;
				}
				DebugPrint("%d: Worker %d report: Resource is destroyed\n" _C_ unit.Player->Index _C_ UnitNumber(unit));
				bool dead = source->IsAlive() == false;

				// Improved version of DropOutAll that makes workers go to the depot.
				LoseResource(unit, *source);
				for (CUnit *uins = source->Resource.Workers;
					 uins; uins = uins->NextWorker) {
					if (uins != &unit && uins->CurrentOrder()->Action == UnitActionResource) {
						COrder_Resource &order = *static_cast<COrder_Resource *>(uins->CurrentOrder());
						if (!uins->Anim.Unbreakable && order.State == SUB_GATHER_RESOURCE) {
							order.LoseResource(*uins, *source);
						}
					}
				}
				// Don't destroy the resource twice.
				// This only happens when it's empty.
				if (!dead) {
					if (Preference.MineNotifications
						&& unit.Player->Index == ThisPlayer->Index
						//Wyrmgus start
//						&& source->Variable[GIVERESOURCE_INDEX].Max > DefaultIncomes[this->CurrentResource]) {
						&& source->Variable[GIVERESOURCE_INDEX].Max > (DefaultIncomes[this->CurrentResource] * 10)) {
						//Wyrmgus end
							//Wyrmgus start
//							unit.Player->Notify(NotifyYellow, source->tilePos, _("%s has collapsed!"), source->Type->Name.c_str());
							unit.Player->Notify(NotifyYellow, source->tilePos, _("Our %s has been depleted!"), source->Type->Name.c_str());
							//Wyrmgus end
					}
					LetUnitDie(*source);
					// FIXME: make the workers inside look for a new resource.
				}
				source = NULL;
				return 0;
			}
		}
		//Wyrmgus start
//		if (resinfo.TerrainHarvester) {
		if (Map.Info.IsPointOnMap(this->goalPos)) {
		//Wyrmgus end
			if (unit.ResourcesHeld == resinfo.ResourceCapacity) {
				// Mark as complete.
				this->DoneHarvesting = true;
			}
			return 0;
		} else {
			//Wyrmgus start
//			if (resinfo.HarvestFromOutside) {
			if (harvest_from_outside) {
			//Wyrmgus end
				if ((unit.ResourcesHeld == resinfo.ResourceCapacity) || (source == NULL)) {
					// Mark as complete.
					this->DoneHarvesting = true;
				}
				return 0;
			} else {
				return unit.ResourcesHeld == resinfo.ResourceCapacity && source;
			}
		}
	}
	return 0;
}
Beispiel #11
0
/**
**  Get the value of the unit variable.
**
**  @param l  Lua state.
**
**  @return   The value of the variable of the unit.
*/
static int CclGetUnitVariable(lua_State *l)
{
	const int nargs = lua_gettop(l);
	Assert(nargs == 2 || nargs == 3);

	lua_pushvalue(l, 1);
	CUnit *unit = CclGetUnit(l);
	if (unit == NULL) {
		return 1;
	}
	UpdateUnitVariables(*unit);
	lua_pop(l, 1);

	const char *const value = LuaToString(l, 2);
	if (!strcmp(value, "RegenerationRate")) {
		lua_pushnumber(l, unit->Variable[HP_INDEX].Increase);
	} else if (!strcmp(value, "Ident")) {
		lua_pushstring(l, unit->Type->Ident.c_str());
	} else if (!strcmp(value, "ResourcesHeld")) {
		lua_pushnumber(l, unit->ResourcesHeld);
	} else if (!strcmp(value, "GiveResourceType")) {
		lua_pushnumber(l, unit->Type->GivesResource);
	} else if (!strcmp(value, "CurrentResource")) {
		lua_pushnumber(l, unit->CurrentResource);
	} else if (!strcmp(value, "Name")) {
		lua_pushstring(l, unit->Type->Name.c_str());
	} else if (!strcmp(value, "PlayerType")) {
		lua_pushinteger(l, unit->Player->Type);
	} else if (!strcmp(value, "IndividualUpgrade")) {
		LuaCheckArgs(l, 3);
		std::string upgrade_ident = LuaToString(l, 3);
		if (CUpgrade::Get(upgrade_ident)) {
			lua_pushboolean(l, unit->IndividualUpgrades[CUpgrade::Get(upgrade_ident)->ID]);
		} else {
			LuaError(l, "Individual upgrade \"%s\" doesn't exist." _C_ upgrade_ident.c_str());
		}
		return 1;
	} else if (!strcmp(value, "Active")) {
		lua_pushboolean(l, unit->Active);
		return 1;
	} else if (!strcmp(value, "Idle")) {
		lua_pushboolean(l, unit->IsIdle());
		return 1;
	} else {
		int index = UnitTypeVar.VariableNameLookup[value];// User variables
		if (index == -1) {
			LuaError(l, "Bad variable name '%s'\n" _C_ value);
		}
		if (nargs == 2) {
			lua_pushnumber(l, unit->Variable[index].Value);
		} else {
			const char *const type = LuaToString(l, 3);
			if (!strcmp(type, "Value")) {
				lua_pushnumber(l, unit->Variable[index].Value);
			} else if (!strcmp(type, "Max")) {
				lua_pushnumber(l, unit->Variable[index].Max);
			} else if (!strcmp(type, "Increase")) {
				lua_pushnumber(l, unit->Variable[index].Increase);
			} else if (!strcmp(type, "Enable")) {
				lua_pushnumber(l, unit->Variable[index].Enable);
			} else {
				LuaError(l, "Bad variable type '%s'\n" _C_ type);
			}
		}
	}
	return 1;
}