예제 #1
0
파일: unit.c 프로젝트: rofl0r/OpenDUNE
/**
 * Check if the given tile is a valid destination. In case of for example
 *  a carry-all it checks if the unit carrying can be placed on destination.
 * In case of structures, it checks if you can walk into it.
 *
 * Stack: 1 - An encoded tile, indicating the destination.
 *
 * @param script The script engine to operate on.
 * @return ??.
 */
uint16 Script_Unit_IsValidDestination(ScriptEngine *script)
{
	Unit *u;
	Unit *u2;
	uint16 encoded;
	uint16 index;

	u = g_scriptCurrentUnit;
	encoded = STACK_PEEK(1);
	index = Tools_Index_Decode(encoded);

	switch (Tools_Index_GetType(encoded)) {
		case IT_TILE:
			if (!Map_IsValidPosition(index)) return 1;
			if (u->o.linkedID == 0xFF) return 1;
			u2 = Unit_Get_ByIndex(u->o.linkedID);
			u2->o.position = Tools_Index_GetTile(encoded);
			if (!Unit_IsTileOccupied(u2)) return 0;
			u2->o.position.tile = 0xFFFFFFFF;
			return 1;

		case IT_STRUCTURE: {
			Structure *s;

			s = Structure_Get_ByIndex(index);
			if (s->o.houseID == Unit_GetHouseID(u)) return 0;
			if (u->o.linkedID == 0xFF) return 1;
			u2 = Unit_Get_ByIndex(u->o.linkedID);
			return Unit_IsValidMovementIntoStructure(u2, s) != 0 ? 1 : 0;
		}

		default: return 1;
	}
}
예제 #2
0
파일: tile.c 프로젝트: l0b0/OpenDUNE
/**
 * Get a tile in the direction of a destination, randomized a bit.
 *
 * @param packed_from The origin.
 * @param packed_to The destination.
 * @return A packed tile.
 */
uint16 Tile_GetTileInDirectionOf(uint16 packed_from, uint16 packed_to)
{
    int16 distance;
    uint8 direction;
    uint8 i;

    if (packed_from == 0 || packed_to == 0) return 0;

    distance = Tile_GetDistancePacked(packed_from, packed_to);
    direction = Tile_GetDirectionPacked(packed_to, packed_from);

    if (distance <= 10) return 0;

    for (i = 0; i < 4; i++) {
        int16 dir;
        tile32 position;
        uint16 packed;

        dir = 29 + (Tools_Random_256() & 0x3F);

        if ((Tools_Random_256() & 1) != 0) dir = -dir;

        position = Tile_UnpackTile(packed_to);
        position = Tile_MoveByDirection(position, direction + dir, min(distance, 20) << 8);
        packed = Tile_PackTile(position);

        if (Map_IsValidPosition(packed)) return packed;
    }

    return 0;
}
예제 #3
0
파일: tile.c 프로젝트: l0b0/OpenDUNE
/**
 * Remove fog in the radius around the given tile.
 *
 * @param tile The tile to remove fog around.
 * @param radius The radius to remove fog around.
 */
void Tile_RemoveFogInRadius(tile32 tile, uint16 radius)
{
    uint16 packed;
    uint16 x, y;
    int16 i, j;

    packed = Tile_PackTile(tile);

    if (!Map_IsValidPosition(packed)) return;

    x = Tile_GetPackedX(packed);
    y = Tile_GetPackedY(packed);
    tile = Tile_MakeXY(x, y);

    for (i = -radius; i <= radius; i++) {
        for (j = -radius; j <= radius; j++) {
            tile32 t;

            if ((x + i) < 0 || (x + i) >= 64) continue;
            if ((y + j) < 0 || (y + j) >= 64) continue;

            packed = Tile_PackXY(x + i, y + j);
            t = Tile_MakeXY(x + i, y + j);

            if (Tile_GetDistanceRoundedUp(tile, t) > radius) continue;

            Map_UnveilTile(packed, g_playerHouseID);
        }
    }
}
예제 #4
0
파일: scenario.c 프로젝트: HBTeun/OpenDUNE
static void Scenario_Load_Unit(const char *key, char *settings)
{
	uint8 houseType, unitType, actionType;
	int8 orientation;
	uint16 hitpoints;
	tile32 position;
	Unit *u;
	char *split;

	VARIABLE_NOT_USED(key);

	/* The value should have 6 values separated by a ',' */
	split = strchr(settings, ',');
	if (split == NULL) return;
	*split = '\0';

	/* First value is the House type */
	houseType = House_StringToType(settings);
	if (houseType == HOUSE_INVALID) return;

	/* Find the next value in the ',' separated list */
	settings = split + 1;
	split = strchr(settings, ',');
	if (split == NULL) return;
	*split = '\0';

	/* Second value is the Unit type */
	unitType = Unit_StringToType(settings);
	if (unitType == UNIT_INVALID) return;

	/* Find the next value in the ',' separated list */
	settings = split + 1;
	split = strchr(settings, ',');
	if (split == NULL) return;
	*split = '\0';

	/* Third value is the Hitpoints in percent (in base 256) */
	hitpoints = atoi(settings);

	/* Find the next value in the ',' separated list */
	settings = split + 1;
	split = strchr(settings, ',');
	if (split == NULL) return;
	*split = '\0';

	/* Fourth value is the position on the map */
	position = Tile_UnpackTile(atoi(settings));

	/* Find the next value in the ',' separated list */
	settings = split + 1;
	split = strchr(settings, ',');
	if (split == NULL) return;
	*split = '\0';

	/* Fifth value is orientation */
	orientation = (int8)((uint8)atoi(settings));

	/* Sixth value is the current state of the unit */
	settings = split + 1;
	actionType = Unit_ActionStringToType(settings);
	if (actionType == ACTION_INVALID) return;


	u = Unit_Allocate(UNIT_INDEX_INVALID, unitType, houseType);
	if (u == NULL) return;
	u->o.flags.s.byScenario = true;

	u->o.hitpoints   = hitpoints * g_table_unitInfo[unitType].o.hitpoints / 256;
	u->o.position    = position;
	u->orientation[0].current = orientation;
	u->actionID     = actionType;
	u->nextActionID = ACTION_INVALID;

	/* In case the above function failed and we are passed campaign 2, don't add the unit */
	if (!Map_IsValidPosition(Tile_PackTile(u->o.position)) && g_campaignID > 2) {
		Unit_Free(u);
		return;
	}

	/* XXX -- There is no way this is ever possible, as the beingBuilt flag is unset by Unit_Allocate() */
	if (!u->o.flags.s.isNotOnMap) Unit_SetAction(u, u->actionID);

	u->o.seenByHouses = 0x00;

	Unit_HouseUnitCount_Add(u, u->o.houseID);

	Unit_SetOrientation(u, u->orientation[0].current, true, 0);
	Unit_SetOrientation(u, u->orientation[0].current, true, 1);
	Unit_SetSpeed(u, 0);
}
예제 #5
0
파일: unit.c 프로젝트: rofl0r/OpenDUNE
/**
 * Delivery of transport, either to structure or to a tile.
 *
 * Stack: *none*.
 *
 * @param script The script engine to operate on.
 * @return One if delivered, zero otherwise..
 */
uint16 Script_Unit_TransportDeliver(ScriptEngine *script)
{
	Unit *u;
	Unit *u2;

	VARIABLE_NOT_USED(script);

	u = g_scriptCurrentUnit;

	if (u->o.linkedID == 0xFF) return 0;
	if (Tools_Index_GetType(u->targetMove) == IT_UNIT) return 0;

	if (Tools_Index_GetType(u->targetMove) == IT_STRUCTURE) {
		const StructureInfo *si;
		Structure *s;

		s = Tools_Index_GetStructure(u->targetMove);
		si = &g_table_structureInfo[s->o.type];

		if (s->o.type == STRUCTURE_STARPORT) {
			uint16 ret = 0;

			if (s->state == STRUCTURE_STATE_BUSY) {
				s->o.linkedID = u->o.linkedID;
				u->o.linkedID = 0xFF;
				u->o.flags.s.inTransport = false;
				u->amount = 0;

				Unit_UpdateMap(2, u);

				Voice_PlayAtTile(24, u->o.position);

				Structure_SetState(s, STRUCTURE_STATE_READY);

				ret = 1;
			}

			Object_Script_Variable4_Clear(&u->o);
			u->targetMove = 0;

			return ret;
		}

		if ((s->state == STRUCTURE_STATE_IDLE || (si->o.flags.busyStateIsIncoming && s->state == STRUCTURE_STATE_BUSY)) && s->o.linkedID == 0xFF) {
			Voice_PlayAtTile(24, u->o.position);

			Unit_EnterStructure(Unit_Get_ByIndex(u->o.linkedID), s);

			Object_Script_Variable4_Clear(&u->o);
			u->targetMove = 0;

			u->o.linkedID = 0xFF;
			u->o.flags.s.inTransport = false;
			u->amount = 0;

			Unit_UpdateMap(2, u);

			return 1;
		}

		Object_Script_Variable4_Clear(&u->o);
		u->targetMove = 0;

		return 0;
	}

	if (!Map_IsValidPosition(Tile_PackTile(Tile_Center(u->o.position)))) return 0;

	u2 = Unit_Get_ByIndex(u->o.linkedID);

	if (!Unit_SetPosition(u2, Tile_Center(u->o.position))) return 0;

	if (u2->o.houseID == g_playerHouseID) {
		Voice_PlayAtTile(24, u->o.position);
	}

	Unit_SetOrientation(u2, u->orientation[0].current, true, 0);
	Unit_SetOrientation(u2, u->orientation[0].current, true, 1);
	Unit_SetSpeed(u2, 0);

	u->o.linkedID = u2->o.linkedID;
	u2->o.linkedID = 0xFF;

	if (u->o.linkedID != 0xFF) return 1;

	u->o.flags.s.inTransport = false;

	Object_Script_Variable4_Clear(&u->o);
	u->targetMove = 0;

	return 1;
}
예제 #6
0
파일: viewport.c 프로젝트: 166MMX/OpenDUNE
/**
 * Draw a single tile on the screen.
 *
 * @param packed The tile to draw.
 */
void GUI_Widget_Viewport_DrawTile(uint16 packed)
{
	uint16 x;
	uint16 y;
	uint16 colour;
	uint16 spriteID;
	Tile *t;
	uint16 mapScale;

	colour = 12;
	spriteID = 0xFFFF;

	if (Tile_IsOutOfMap(packed) || !Map_IsValidPosition(packed)) return;

	x = Tile_GetPackedX(packed);
	y = Tile_GetPackedY(packed);

	mapScale = g_scenario.mapScale + 1;

	if (mapScale == 0 || BitArray_Test(g_displayedMinimap, packed)) return;

	t = &g_map[packed];

	if ((t->isUnveiled && g_playerHouse->flags.radarActivated) || g_debugScenario) {
		uint16 type = Map_GetLandscapeType(packed);
		Unit *u;

		if (mapScale > 1) {
			spriteID = g_scenario.mapScale + g_table_landscapeInfo[type].spriteID - 1;
		} else {
			colour = g_table_landscapeInfo[type].radarColour;
		}

		if (g_table_landscapeInfo[type].radarColour == 0xFFFF) {
			if (mapScale > 1) {
				spriteID = mapScale + t->houseID * 2 + 29;
			} else {
				colour = g_table_houseInfo[t->houseID].minimapColor;
			}
		}

		u = Unit_Get_ByPackedTile(packed);

		if (u != NULL) {
			if (mapScale > 1) {
				if (u->o.type == UNIT_SANDWORM) {
					spriteID = mapScale + 53;
				} else {
					spriteID = mapScale + Unit_GetHouseID(u) * 2 + 29;
				}
			} else {
				if (u->o.type == UNIT_SANDWORM) {
					colour = 255;
				} else {
					colour = g_table_houseInfo[Unit_GetHouseID(u)].minimapColor;
				}
			}
		}
	} else {
		Structure *s;

		s = Structure_Get_ByPackedTile(packed);

		if (s != NULL && s->o.houseID == g_playerHouseID) {
			if (mapScale > 1) {
				spriteID = mapScale + s->o.houseID * 2 + 29;
			} else {
				colour = g_table_houseInfo[s->o.houseID].minimapColor;
			}
		} else {
			if (mapScale > 1) {
				spriteID = g_scenario.mapScale + g_table_landscapeInfo[LST_ENTIRELY_MOUNTAIN].spriteID - 1;
			} else {
				colour = 12;
			}
		}
	}

	x -= g_mapInfos[g_scenario.mapScale].minX;
	y -= g_mapInfos[g_scenario.mapScale].minY;

	if (spriteID != 0xFFFF) {
		x *= g_scenario.mapScale + 1;
		y *= g_scenario.mapScale + 1;
		GUI_DrawSprite(g_screenActiveID, g_sprites[spriteID], x, y, 3, 0x4000);
	} else {
		GFX_PutPixel(x + 256, y + 136, colour & 0xFF);
	}
}