/** ** Send command: Unit harvest resources ** ** @param unit pointer to unit. ** @param dest pointer to destination (oil-platform,gold mine). ** @param flush Flag flush all pending commands. */ void SendCommandResource(CUnit &unit, CUnit &dest, int flush) { if (!IsNetworkGame()) { CommandLog("resource", &unit, flush, -1, -1, &dest, NULL, -1); CommandResource(unit, dest, flush); } else { NetworkSendCommand(MessageCommandResource, unit, 0, 0, &dest, 0, flush); } }
/** ** Assign worker to gather a certain resource from Unit. ** ** @param unit pointer to the unit. ** @param resource resource identification. ** ** @return 1 if the worker was assigned, 0 otherwise. */ static int AiAssignHarvesterFromUnit(CUnit &unit, int resource) { // Try to find the nearest depot first. CUnit *depot = FindDeposit(unit, 1000, resource); // Find a resource to harvest from. CUnit *mine = UnitFindResource(unit, depot ? *depot : unit, 1000, resource, true); if (mine) { CommandResource(unit, *mine, FlushCommands); return 1; } int exploremask = 0; for (size_t i = 0; i != UnitTypes.size(); ++i) { const CUnitType *type = UnitTypes[i]; if (type && type->GivesResource == resource) { switch (type->UnitType) { case UnitTypeLand: exploremask |= MapFieldLandUnit; break; case UnitTypeFly: exploremask |= MapFieldAirUnit; break; case UnitTypeNaval: exploremask |= MapFieldSeaUnit; break; default: Assert(0); } } } // Ask the AI to explore AiExplore(unit.tilePos, exploremask); // Failed. return 0; }
/** ** Execute a command (from network). ** ** @param msgnr Network message type ** @param unum Unit number (slot) that receive the command. ** @param x optional X map position. ** @param y optional y map position. ** @param dstnr optional destination unit. */ void ExecCommand(unsigned char msgnr, UnitRef unum, unsigned short x, unsigned short y, UnitRef dstnr) { CUnit &unit = UnitManager.GetSlotUnit(unum); const Vec2i pos(x, y); const int arg1 = x; const int arg2 = y; // // Check if unit is already killed? // if (unit.Destroyed) { DebugPrint(" destroyed unit skipping %d\n" _C_ UnitNumber(unit)); return; } Assert(unit.Type); const int status = (msgnr & 0x80) >> 7; // Note: destroyed destination unit is handled by the action routines. switch (msgnr & 0x7F) { case MessageSync: return; case MessageQuit: return; case MessageChat: return; case MessageCommandStop: CommandLog("stop", &unit, FlushCommands, -1, -1, NoUnitP, NULL, -1); CommandStopUnit(unit); break; case MessageCommandStand: CommandLog("stand-ground", &unit, status, -1, -1, NoUnitP, NULL, -1); CommandStandGround(unit, status); break; case MessageCommandDefend: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("defend", &unit, status, -1, -1, &dest, NULL, -1); CommandDefend(unit, dest, status); } break; } case MessageCommandFollow: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("follow", &unit, status, -1, -1, &dest, NULL, -1); CommandFollow(unit, dest, status); } break; } case MessageCommandMove: //Wyrmgus start // CommandLog("move", &unit, status, pos.x, pos.y, NoUnitP, NULL, -1); // CommandMove(unit, pos, status); if (!unit.CanMove()) { //FIXME: find better way to identify whether the unit should move or set a rally point CommandLog("rally-point", &unit, status, pos.x, pos.y, NoUnitP, NULL, -1); CommandRallyPoint(unit, pos); } else { CommandLog("move", &unit, status, pos.x, pos.y, NoUnitP, NULL, -1); CommandMove(unit, pos, status); } //Wyrmgus end break; //Wyrmgus start case MessageCommandPickUp: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("pick-up", &unit, status, -1, -1, &dest, NULL, -1); CommandPickUp(unit, dest, status); } break; } //Wyrmgus end case MessageCommandRepair: { CUnit *dest = NoUnitP; if (dstnr != (unsigned short)0xFFFF) { dest = &UnitManager.GetSlotUnit(dstnr); Assert(dest && dest->Type); } CommandLog("repair", &unit, status, pos.x, pos.y, dest, NULL, -1); CommandRepair(unit, pos, dest, status); break; } case MessageCommandAutoRepair: CommandLog("auto-repair", &unit, status, arg1, arg2, NoUnitP, NULL, 0); CommandAutoRepair(unit, arg1); break; case MessageCommandAttack: { CUnit *dest = NoUnitP; if (dstnr != (unsigned short)0xFFFF) { dest = &UnitManager.GetSlotUnit(dstnr); Assert(dest && dest->Type); } CommandLog("attack", &unit, status, pos.x, pos.y, dest, NULL, -1); CommandAttack(unit, pos, dest, status); break; } case MessageCommandGround: CommandLog("attack-ground", &unit, status, pos.x, pos.y, NoUnitP, NULL, -1); CommandAttackGround(unit, pos, status); break; //Wyrmgus start case MessageCommandUse: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("use", &unit, status, -1, -1, &dest, NULL, -1); CommandUse(unit, dest, status); } break; } //Wyrmgus end case MessageCommandPatrol: CommandLog("patrol", &unit, status, pos.x, pos.y, NoUnitP, NULL, -1); CommandPatrolUnit(unit, pos, status); break; case MessageCommandBoard: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("board", &unit, status, arg1, arg2, &dest, NULL, -1); CommandBoard(unit, dest, status); } break; } case MessageCommandUnload: { CUnit *dest = NULL; if (dstnr != (unsigned short)0xFFFF) { dest = &UnitManager.GetSlotUnit(dstnr); Assert(dest && dest->Type); } CommandLog("unload", &unit, status, pos.x, pos.y, dest, NULL, -1); CommandUnload(unit, pos, dest, status); break; } case MessageCommandBuild: CommandLog("build", &unit, status, pos.x, pos.y, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), -1); CommandBuildBuilding(unit, pos, *UnitTypes[dstnr], status); break; case MessageCommandDismiss: CommandLog("dismiss", &unit, FlushCommands, -1, -1, NULL, NULL, -1); CommandDismiss(unit); break; case MessageCommandResourceLoc: CommandLog("resource-loc", &unit, status, pos.x, pos.y, NoUnitP, NULL, -1); CommandResourceLoc(unit, pos, status); break; case MessageCommandResource: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("resource", &unit, status, -1, -1, &dest, NULL, -1); CommandResource(unit, dest, status); } break; } case MessageCommandReturn: { CUnit *dest = (dstnr != (unsigned short)0xFFFF) ? &UnitManager.GetSlotUnit(dstnr) : NULL; CommandLog("return", &unit, status, -1, -1, dest, NULL, -1); CommandReturnGoods(unit, dest, status); break; } case MessageCommandTrain: //Wyrmgus start // CommandLog("train", &unit, status, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), -1); // CommandTrainUnit(unit, *UnitTypes[dstnr], status); CommandLog("train", &unit, status, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), arg1); // use X as a way to mark the player CommandTrainUnit(unit, *UnitTypes[dstnr], arg1, status); //Wyrmgus end break; case MessageCommandCancelTrain: // We need (short)x for the last slot -1 if (dstnr != (unsigned short)0xFFFF) { CommandLog("cancel-train", &unit, FlushCommands, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), (short)x); CommandCancelTraining(unit, (short)x, UnitTypes[dstnr]); } else { CommandLog("cancel-train", &unit, FlushCommands, -1, -1, NoUnitP, NULL, (short)x); CommandCancelTraining(unit, (short)x, NULL); } break; case MessageCommandUpgrade: //Wyrmgus start /* CommandLog("upgrade-to", &unit, status, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), -1); CommandUpgradeTo(unit, *UnitTypes[dstnr], status); break; */ if (arg1 == 2) { //use X as a way to mark whether this is an upgrade or a transformation CommandLog("transform-into", &unit, status, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), -1); CommandTransformIntoType(unit, *UnitTypes[dstnr]); } else { CommandLog("upgrade-to", &unit, status, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), -1); CommandUpgradeTo(unit, *UnitTypes[dstnr], status); } break; //Wyrmgus end case MessageCommandCancelUpgrade: CommandLog("cancel-upgrade-to", &unit, FlushCommands, -1, -1, NoUnitP, NULL, -1); CommandCancelUpgradeTo(unit); break; case MessageCommandResearch: CommandLog("research", &unit, status, -1, -1, NoUnitP, AllUpgrades[arg1]->Ident.c_str(), -1); CommandResearch(unit, *AllUpgrades[arg1], status); break; case MessageCommandCancelResearch: CommandLog("cancel-research", &unit, FlushCommands, -1, -1, NoUnitP, NULL, -1); CommandCancelResearch(unit); break; //Wyrmgus start case MessageCommandQuest: { CommandLog("quest", &unit, 0, 0, 0, NoUnitP, Quests[arg1]->Ident.c_str(), -1); CommandQuest(unit, Quests[arg1]); break; } case MessageCommandBuy: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("buy", &unit, 0, -1, -1, &dest, NULL, arg1); CommandBuy(unit, &dest, arg1); } break; } //Wyrmgus end default: { int id = (msgnr & 0x7f) - MessageCommandSpellCast; if (arg2 != (unsigned short)0xFFFF) { CUnit *dest = NULL; if (dstnr != (unsigned short)0xFFFF) { dest = &UnitManager.GetSlotUnit(dstnr); Assert(dest && dest->Type); } CommandLog("spell-cast", &unit, status, pos.x, pos.y, dest, NULL, id); CommandSpellCast(unit, pos, dest, *SpellTypeTable[id], status); } else { CommandLog("auto-spell-cast", &unit, status, arg1, -1, NoUnitP, NULL, id); CommandAutoSpellCast(unit, id, arg1); } break; } } }
/** ** Assign worker to gather a certain resource. ** ** @param unit pointer to the unit. ** @param resource resource identification. ** ** @return 1 if the worker was assigned, 0 otherwise. */ static int AiAssignHarvester(CUnit &unit, int resource) { ResourceInfo *resinfo; // It can't. if (unit.Removed) { return 0; } resinfo = unit.Type->ResInfo[resource]; Assert(resinfo); if (resinfo->TerrainHarvester) { Vec2i forestPos; // // Code for terrain harvesters. Search for piece of terrain to mine. // if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 1000, unit.Player, unit.tilePos, &forestPos)) { CommandResourceLoc(unit, forestPos, FlushCommands); return 1; } // Ask the AI to explore... AiExplore(unit.tilePos, MapFieldLandUnit); } else { int exploremask = 0; // // Find a resource to harvest from. // CUnit *dest = UnitFindResource(unit, unit.tilePos.x, unit.tilePos.y, 1000, resource, true); if (dest) { //FIXME: rb - when workers can speedup building then such assign may be ok. //if(dest->CurrentAction() == UnitActionBuilt) //CommandBuildBuilding(unit, dest->tilePos, dest->Type, FlushCommands); //else CommandResource(unit, *dest, FlushCommands); return 1; } #if 0 //may this code touch needmask which will be reseted before next cycle if (resinfo->RefineryHarvester && (dest = UnitFindMiningArea(unit, unit.X, unit.Y, 1000, resource))) { int needmask; //int counter[UnitTypeMax]; // // Count the already made build requests. // //AiGetBuildRequestsCount(counter); int n = AiHelpers.Refinery[resource - 1].size(); for (int i = 0; i < n; ++i) { CUnitType *type = AiHelpers.Refinery[resource - 1][i]; //if (counter[type->Slot]) { // Already ordered. // return 0; //} if (!AiRequestedTypeAllowed(AiPlayer->Player, type)) { continue; } // // Check if resources available. // needmask = AiCheckUnitTypeCosts(type); if(!needmask && AiMakeUnit(type)) { AiBuildQueue newqueue; newqueue.Type = type; newqueue.Want = 1; newqueue.Made = 1; newqueue.X = dest->X; newqueue.Y = dest->Y; AiPlayer->UnitTypeBuilt.insert( AiPlayer->UnitTypeBuilt.begin(), newqueue); return 0; } } return 0; } #endif for (std::vector<CUnitType *>::iterator i = UnitTypes.begin(); i != UnitTypes.end(); i++) { if (*i && (*i)->GivesResource == resource) { switch ((*i)->UnitType) { case UnitTypeLand: exploremask |= MapFieldLandUnit; break; case UnitTypeFly: exploremask |= MapFieldAirUnit; break; case UnitTypeNaval: exploremask |= MapFieldSeaUnit; break; default: Assert(0); } } } // Ask the AI to explore AiExplore(unit.tilePos, exploremask); } // Failed. return 0; }
static void Finish(COrder_Built &order, CUnit &unit) { const CUnitType &type = *unit.Type; CPlayer &player = *unit.Player; DebugPrint("%d: Building %s(%s) ready.\n" _C_ player.Index _C_ type.Ident.c_str() _C_ type.Name.c_str()); // HACK: the building is ready now player.UnitTypesCount[type.Slot]++; if (unit.Active) { player.UnitTypesAiActiveCount[type.Slot]++; } unit.Constructed = 0; if (unit.Frame < 0) { unit.Frame = -1; } else { unit.Frame = 0; } CUnit *worker = order.GetWorkerPtr(); if (worker != NULL) { if (type.BoolFlag[BUILDERLOST_INDEX].value) { // Bye bye worker. LetUnitDie(*worker); worker = NULL; } else { // Drop out the worker. worker->ClearAction(); DropOutOnSide(*worker, LookingW, &unit); // If we can harvest from the new building, do it. if (worker->Type->ResInfo[type.GivesResource]) { CommandResource(*worker, unit, 0); } // If we can reurn goods to a new depot, do it. if (worker->CurrentResource && worker->ResourcesHeld > 0 && type.CanStore[worker->CurrentResource]) { CommandReturnGoods(*worker, &unit, 0); } } } if (type.GivesResource && type.StartingResources != 0) { // Has StartingResources, Use those unit.ResourcesHeld = type.StartingResources; } player.Notify(NotifyGreen, unit.tilePos, _("New %s done"), type.Name.c_str()); if (&player == ThisPlayer) { if (type.MapSound.Ready.Sound) { PlayUnitSound(unit, VoiceReady); } else if (worker) { PlayUnitSound(*worker, VoiceWorkCompleted); } else { PlayUnitSound(unit, VoiceBuilding); } } if (player.AiEnabled) { /* Worker can be NULL */ AiWorkComplete(worker, unit); } // FIXME: Vladi: this is just a hack to test wall fixing, // FIXME: also not sure if the right place... // FIXME: Johns: hardcoded unit-type wall / more races! if (&type == UnitTypeOrcWall || &type == UnitTypeHumanWall) { Map.SetWall(unit.tilePos, &type == UnitTypeHumanWall); unit.Remove(NULL); UnitLost(unit); UnitClearOrders(unit); unit.Release(); return ; } UpdateForNewUnit(unit, 0); // Set the direction of the building if it supports them if (type.NumDirections > 1 && type.BoolFlag[NORANDOMPLACING_INDEX].value == false) { if (type.BoolFlag[WALL_INDEX].value) { // Special logic for walls CorrectWallDirections(unit); CorrectWallNeighBours(unit); } else { unit.Direction = (MyRand() >> 8) & 0xFF; // random heading } UnitUpdateHeading(unit); } if (IsOnlySelected(unit) || &player == ThisPlayer) { SelectedUnitChanged(); } MapUnmarkUnitSight(unit); unit.CurrentSightRange = unit.Stats->Variables[SIGHTRANGE_INDEX].Max; MapMarkUnitSight(unit); order.Finished = true; }
//Wyrmgus start //static int AiAssignHarvesterFromUnit(CUnit &unit, int resource) static int AiAssignHarvesterFromUnit(CUnit &unit, int resource, int resource_range) //Wyrmgus end { // Try to find the nearest depot first. CUnit *depot = FindDeposit(unit, 1000, resource); // Find a resource to harvest from. //Wyrmgus start // CUnit *mine = UnitFindResource(unit, depot ? *depot : unit, 1000, resource, true); CUnit *mine = UnitFindResource(unit, depot ? *depot : unit, resource_range, resource, true, NULL, false); //Wyrmgus end if (mine) { //Wyrmgus start // CommandResource(unit, *mine, FlushCommands); // return 1; if (mine->Type->BoolFlag[CANHARVEST_INDEX].value) { CommandResource(unit, *mine, FlushCommands); return 1; } else { // if the resource isn't readily harvestable (but is a deposit), build a mine there const int n = AiHelpers.Refinery[resource - 1].size(); for (int i = 0; i < n; ++i) { CUnitType &type = *AiHelpers.Refinery[resource - 1][i]; if (CanBuildUnitType(&unit, type, mine->tilePos, 1, true, mine->MapLayer)) { CommandBuildBuilding(unit, mine->tilePos, type, FlushCommands, mine->MapLayer); return 1; } } } //Wyrmgus end } //Wyrmgus start /* int exploremask = 0; for (size_t i = 0; i != UnitTypes.size(); ++i) { const CUnitType *type = UnitTypes[i]; if (type && type->GivesResource == resource) { switch (type->UnitType) { case UnitTypeLand: exploremask |= MapFieldLandUnit; break; case UnitTypeFly: exploremask |= MapFieldAirUnit; break; //Wyrmgus start case UnitTypeFlyLow: exploremask |= MapFieldLandUnit; break; //Wyrmgus end case UnitTypeNaval: exploremask |= MapFieldSeaUnit; break; default: Assert(0); } } } // Ask the AI to explore AiExplore(unit.tilePos, exploremask); */ //Wyrmgus end // Failed. return 0; }