Exemplo n.º 1
0
/**
**  Create a unit and place it on the map
**
**  @param l  Lua state.
**
**  @return   Returns the slot number of the made unit.
*/
static int CclCreateUnit(lua_State *l)
{
	LuaCheckArgs(l, 3);

	lua_pushvalue(l, 1);
	CUnitType *unittype = CclGetUnitType(l);
	if (unittype == NULL) {
		LuaError(l, "Bad unittype");
	}
	lua_pop(l, 1);
	Vec2i ipos;
	CclGetPos(l, &ipos.x, &ipos.y, 3);

	lua_pushvalue(l, 2);
	const int playerno = TriggerGetPlayer(l);
	lua_pop(l, 1);
	if (playerno == -1) {
		printf("CreateUnit: You cannot use \"any\" in create-unit, specify a player\n");
		LuaError(l, "bad player");
		return 0;
	}
	if (Players[playerno].Type == PlayerNobody) {
		printf("CreateUnit: player %d does not exist\n", playerno);
		LuaError(l, "bad player");
		return 0;
	}
	CUnit *unit = MakeUnit(*unittype, &Players[playerno]);
	if (unit == NULL) {
		DebugPrint("Unable to allocate unit");
		return 0;
	} else {
		if (UnitCanBeAt(*unit, ipos)
			|| (unit->Type->Building && CanBuildUnitType(NULL, *unit->Type, ipos, 0))) {
			unit->Place(ipos);
		} else {
			const int heading = SyncRand() % 256;

			unit->tilePos = ipos;
			DropOutOnSide(*unit, heading, NULL);
		}
		UpdateForNewUnit(*unit, 0);

		lua_pushnumber(l, UnitNumber(*unit));
		return 1;
	}
}
Exemplo n.º 2
0
/**
**  Check if the unit can build
**
**  @param unit  Unit to check
*/
CUnit *COrder_Build::CheckCanBuild(CUnit &unit)
{
	const Vec2i pos = this->goalPos;
	const CUnitType &type = this->GetUnitType();

	// Check if the building could be built there.

	CUnit *ontop = CanBuildUnitType(&unit, type, pos, 1);

	if (ontop != NULL) {
		return ontop;
	}
#if 0
	/*
	 * FIXME: rb - CheckAlreadyBuilding should be somehow
	 * enabled/disable via game lua scripting
	 */
	CUnit *building = AlreadyBuildingFinder(unit, type).Find(Map.Field(pos));
	if (building != NULL) {
		if (unit.CurrentOrder() == this) {
			DebugPrint("%d: Worker [%d] is helping build: %s [%d]\n"
					   _C_ unit.Player->Index _C_ unit.Slot
					   _C_ building->Type->Name.c_str()
					   _C_ building->Slot);

			delete this; // Bad
			unit.Orders[0] = COrder::NewActionRepair(unit, *building);
			return NULL;
		}
	}
#endif
	// Some tries to build the building.
	this->State++;
	// To keep the load low, retry each 10 cycles
	// NOTE: we can already inform the AI about this problem?
	unit.Wait = 10;
	return NULL;
}
Exemplo n.º 3
0
/**
**  Find free building place. (flood fill version)
**
**  @param worker  Worker to build building.
**  @param type    Type of building.
**  @param ox      Original X position to try building
**  @param oy      Original Y position to try building
**  @param dpos    Pointer for position returned.
**
**  @return        True if place found, false if no found.
*/
static int AiFindBuildingPlace2(const CUnit &worker, const CUnitType &type, int ox, int oy, Vec2i *dpos)
{
    const Vec2i offset[] = {{0, -1}, {-1, 0}, {1, 0}, {0, 1}, {-1, -1}, {1, -1}, {-1, 1}, {1, 1}};
    Vec2i *points;
    int size;
    Vec2i pos = {ox, oy};
    Vec2i rpos;
    int mask;
    int wp;
    int rp;
    int ep;
    unsigned char *m;
    Vec2i backupPos = {-1, -1};
    bool backupok;

    //
    // Look if we can build at current place.
    //
    if (CanBuildUnitType(&worker, type, pos, 1) &&
            !AiEnemyUnitsInDistance(worker.Player, NULL, pos, 8)) {
        if (AiCheckSurrounding(worker, type, pos.x, pos.y, backupok)) {
            *dpos = pos;
            return 1;
        } else if (backupok) {
            backupPos = pos;
        }
    }

    size = Map.Info.MapWidth * Map.Info.MapHeight / 4;
    points = new Vec2i[size];

    //
    //  Make movement matrix.
    //
    unsigned char *matrix = CreateMatrix();
    const int w = Map.Info.MapWidth + 2;

    mask = worker.Type->MovementMask;
    // Ignore all possible mobile units.
    mask &= ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit);

    points[0] = pos;
    // also use the bottom right
    if ((type.TileWidth > 1 || type.TileHeight > 1) &&
            pos.x + type.TileWidth - 1 < Map.Info.MapWidth &&
            pos.y + type.TileHeight - 1 < Map.Info.MapHeight) {
        points[1].x = pos.x + type.TileWidth - 1;
        points[1].y = pos.y + type.TileHeight - 1;
        ep = wp = 2; // start with two points
    } else {
        ep = wp = 1; // start with one point
    }
    matrix += w + w + 2;
    rp = 0;
    matrix[pos.x + pos.y * w] = 1; // mark start point

    //
    // Pop a point from stack, push all neighbours which could be entered.
    //
    for (;;) {
        while (rp != ep) {
            rpos = points[rp];
            for (int i = 0; i < 8; ++i) { // mark all neighbors
                pos = rpos + offset[i];
                m = matrix + pos.x + pos.y * w;
                if (*m) { // already checked
                    continue;
                }

                //
                // Look if we can build here and no enemies nearby.
                //
                if (CanBuildUnitType(&worker, type, pos, 1) &&
                        !AiEnemyUnitsInDistance(worker.Player, NULL, pos, 8)) {
                    if (AiCheckSurrounding(worker, type, pos.x, pos.y, backupok)) {
                        *dpos = pos;
                        delete[] points;
                        return 1;
                    } else if (backupok && backupPos.x == -1) {
                        backupPos = pos;
                    }
                }

                if (CanMoveToMask(pos, mask)) { // reachable
                    *m = 1;
                    points[wp] = pos; // push the point
                    if (++wp >= size) { // round about
                        wp = 0;
                    }
                } else { // unreachable
                    *m = 99;
                }
            }

            if (++rp >= size) { // round about
                rp = 0;
            }
        }

        //
        // Continue with next frame.
        //
        if (rp == wp) { // unreachable, no more points available
            break;
        }
        ep = wp;
    }
    delete[] points;

    if (backupPos.x != -1) {
        *dpos = backupPos;
        return 1;
    }
    return 0;
}
Exemplo n.º 4
0
//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;
}
Exemplo n.º 5
0
//Wyrmgus start
//void EditorChangeTile(const Vec2i &pos, int tileIndex, int d)
void EditorChangeTile(const Vec2i &pos, int tileIndex)
//Wyrmgus end
{
	//Wyrmgus start
//	Assert(Map.Info.IsPointOnMap(pos));
	Assert(Map.Info.IsPointOnMap(pos, CurrentMapLayer));
	//Wyrmgus end

	// Change the flags
	//Wyrmgus start
//	CMapField &mf = *Map.Field(pos);
	CMapField &mf = *Map.Field(pos, CurrentMapLayer);
	//Wyrmgus end
	int tile = tileIndex;
	if (TileToolRandom) {
		int n = 0;
		for (int i = 0; i < 16; ++i) {
			if (!Map.Tileset->tiles[tile + i].tile) {
				break;
			} else {
				++n;
			}
		}
		n = MyRand() % n;
		int i = -1;
		do {
			while (++i < 16 && !Map.Tileset->tiles[tile + i].tile) {
			}
		} while (i < 16 && n--);
		Assert(i != 16);
		tile += i;
	}
	//Wyrmgus start
	mf.setTileIndex(*Map.Tileset, tile, 0);
//	mf.playerInfo.SeenTile = mf.getGraphicTile();
	mf.UpdateSeenTile();
	//Wyrmgus end
	
	//Wyrmgus start
	Map.CalculateTileTransitions(pos, false, CurrentMapLayer);
	Map.CalculateTileTransitions(pos, true, CurrentMapLayer);
	
	for (int x_offset = -1; x_offset <= 1; ++x_offset) {
		for (int y_offset = -1; y_offset <= 1; ++y_offset) {
			if (x_offset != 0 || y_offset != 0) {
				Vec2i adjacent_pos(pos.x + x_offset, pos.y + y_offset);
				if (Map.Info.IsPointOnMap(adjacent_pos, CurrentMapLayer)) {
					Map.CalculateTileTransitions(adjacent_pos, false, CurrentMapLayer);
					Map.CalculateTileTransitions(adjacent_pos, true, CurrentMapLayer);
				}
			}
		}
	}
	//Wyrmgus end
	
	//Wyrmgus start
	CUnitCache &unitcache = mf.UnitCache;
	std::vector<CUnit *> units_to_remove;

	for (CUnitCache::iterator it = unitcache.begin(); it != unitcache.end(); ++it) {
		CUnit *unit = *it;

		if (!CanBuildUnitType(unit, *unit->Type, pos, 1, true, CurrentMapLayer)) {
			units_to_remove.push_back(unit);
		}
	}
	
	for (size_t i = 0; i < units_to_remove.size(); ++i) {
		EditorActionRemoveUnit(*units_to_remove[i], false);
	}
	//Wyrmgus end

	UI.Minimap.UpdateSeenXY(pos);
	//Wyrmgus start
//	UI.Minimap.UpdateXY(pos);
	UI.Minimap.UpdateXY(pos, CurrentMapLayer);
	//Wyrmgus end

	//Wyrmgus start
//	EditorChangeSurrounding(pos, d);
	EditorChangeSurrounding(pos, tile);
	//Wyrmgus end
}