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; }
/** ** 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); } }
/** ** 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; }
/** ** 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); } }
/** ** 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); } }
/** ** 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 }
/** ** 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; } }
/** ** 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); } } }
/** ** 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; }
/** ** 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; }