Beispiel #1
0
/**
 * Tries to add the closest unit to the current team.
 *
 * Stack: *none*.
 *
 * @param script The script engine to operate on.
 * @return The amount of space left in current team.
 */
uint16 Script_Team_AddClosestUnit(ScriptEngine *script)
{
	Team *t;
	Unit *closest = NULL;
	Unit *closest2 = NULL;
	uint16 minDistance = 0;
	uint16 minDistance2 = 0;
	PoolFindStruct find;

	VARIABLE_NOT_USED(script);

	t = g_scriptCurrentTeam;

	if (t->members >= t->maxMembers) return 0;

	find.houseID = t->houseID;
	find.index   = 0xFFFF;
	find.type    = 0xFFFF;

	while (true) {
		Unit *u;
		Team *t2;
		uint16 distance;

		u = Unit_Find(&find);
		if (u == NULL) break;
		if (!u->o.flags.s.byScenario) continue;
		if (u->o.type == UNIT_SABOTEUR) continue;
		if (g_table_unitInfo[u->o.type].movementType != t->movementType) continue;
		if (u->team == 0) {
			distance = Tile_GetDistance(t->position, u->o.position);
			if (distance >= minDistance && minDistance != 0) continue;
			minDistance = distance;
			closest = u;
			continue;
		}

		t2 = Team_Get_ByIndex(u->team - 1);
		if (t2->members > t2->minMembers) continue;

		distance = Tile_GetDistance(t->position, u->o.position);
		if (distance >= minDistance2 && minDistance2 != 0) continue;
		minDistance2 = distance;
		closest2 = u;
	}

	if (closest == NULL) closest = closest2;
	if (closest == NULL) return 0;

	Unit_RemoveFromTeam(closest);
	return Unit_AddToTeam(closest, t);
}
Beispiel #2
0
/**
 * Gets the distance from the given object to the given encoded index.
 * @param o The object.
 * @param encoded The encoded index.
 * @return The distance.
 */
uint16 Object_GetDistanceToEncoded(Object* o, uint16 encoded)
{
	Structure* s;
	tile32 position;

	s = Tools_Index_GetStructure(encoded);

	if (s != NULL)
	{
		uint16 packed;

		position = s->o.position;
		packed = Tile_PackTile(position);

		packed += g_table_structure_layoutEdgeTiles[g_table_structureInfo[o->type].layout][(Orientation_256To8(Tile_GetDirection(o->position, position)) + 4) & 7];

		position = Tile_UnpackTile(packed);
	}
	else
	{
		position = Tools_Index_GetTile(encoded);
	}

	return Tile_GetDistance(o->position, position);
}
Beispiel #3
0
/**
 * Unknown function 0788.
 *
 * Stack: *none*.
 *
 * @param script The script engine to operate on.
 * @return The value 0. Always.
 */
uint16 Script_Team_Unknown0788(ScriptEngine *script)
{
	Team *t;
	tile32 tile;
	PoolFindStruct find;

	VARIABLE_NOT_USED(script);

	t = g_scriptCurrentTeam;
	if (t->target == 0) return 0;

	tile = Tools_Index_GetTile(t->target);

	find.houseID = t->houseID;
	find.index   = 0xFFFF;
	find.type    = 0xFFFF;

	while (true) {
		Unit *u;
		uint16 distance;
		uint16 packed;
		int16 orientation;

		u = Unit_Find(&find);
		if (u == NULL) break;
		if (u->team - 1 != t->index) continue;
		if (t->target == 0) {
			Unit_SetAction(u, ACTION_GUARD);
			continue;
		}

		distance = g_table_unitInfo[u->o.type].fireDistance << 8;
		if (u->actionID == ACTION_ATTACK && u->targetAttack == t->target) {
			if (u->targetMove != 0) continue;
			if (Tile_GetDistance(u->o.position, tile) >= distance) continue;
		}

		if (u->actionID != ACTION_ATTACK) Unit_SetAction(u, ACTION_ATTACK);

		orientation = (Tile_GetDirection(tile, u->o.position) & 0xC0) + Tools_RandomLCG_Range(0, 127);
		if (orientation < 0) orientation += 256;

		packed = Tile_PackTile(Tile_MoveByDirection(tile, orientation, distance));

		if (Object_GetByPackedTile(packed) == NULL) {
			Unit_SetDestination(u, Tools_Index_Encode(packed, IT_TILE));
		} else {
			Unit_SetDestination(u, Tools_Index_Encode(Tile_PackTile(tile), IT_TILE));
		}

		Unit_SetTarget(u, t->target);
	}

	return 0;
}
Beispiel #4
0
/**
 * Move the Unit to the target, and keep repeating this function till we
 *  arrived there. When closing in on the target it will slow down the Unit.
 * It is wise to only use this function on Carry-Alls.
 *
 * Stack: *none*.
 *
 * @param script The script engine to operate on.
 * @return 1 if arrived, 0 if still busy.
 */
uint16 Script_Unit_MoveToTarget(ScriptEngine *script)
{
	Unit *u;
	uint16 delay;
	tile32 tile;
	uint16 distance;
	int8 orientation;
	int16 diff;

	u = g_scriptCurrentUnit;

	if (u->targetMove == 0) return 0;

	tile = Tools_Index_GetTile(u->targetMove);

	distance = Tile_GetDistance(u->o.position, tile);

	if ((int16)distance < 128) {
		Unit_SetSpeed(u, 0);

		u->o.position.s.x += clamp((int16)(tile.s.x - u->o.position.s.x), -16, 16);
		u->o.position.s.y += clamp((int16)(tile.s.y - u->o.position.s.y), -16, 16);

		Unit_UpdateMap(2, u);

		if ((int16)distance < 32) return 1;

		script->delay = 2;

		script->script--;
		return 0;
	}

	orientation = Tile_GetDirection(u->o.position, tile);

	Unit_SetOrientation(u, orientation, false, 0);

	diff = abs(orientation - u->orientation[0].current);
	if (diff > 128) diff = 256 - diff;

	Unit_SetSpeed(u, (Tools_AdjustToGameSpeed(min(distance / 8, 255), 25, 255, true) * (255 - diff) + 128) / 256);

	delay = max((int16)distance / 1024, 1);

	Unit_UpdateMap(2, u);

	if (delay != 0) {
		script->delay = delay;

		script->script--;
	}

	return 0;
}
Beispiel #5
0
/**
 * Find a Unit which is within range and not an ally.
 *
 * Stack: 1 - Range to find a target in (amount of tiles multiplied with 256).
 *
 * @param script The script engine to operate on.
 * @return The Unit Index of the closest unit within range and not friendly,
 *   or 0 if none exists.
 */
uint16 Script_Structure_FindTargetUnit(ScriptEngine *script)
{
	PoolFindStruct find;
	Structure *s;
	Unit *u;
	uint32 distanceCurrent;
	uint32 targetRange;

	s = g_scriptCurrentStructure;
	targetRange = STACK_PEEK(1);
	distanceCurrent = 32000;
	u = NULL;

	find.houseID = HOUSE_INVALID;
	find.index   = 0xFFFF;
	find.type    = 0xFFFF;

	while (true) {
		uint16 distance;
		Unit *uf;

		uf = Unit_Find(&find);
		if (uf == NULL) break;

		if (House_AreAllied(s->o.houseID, uf->o.houseID)) continue;

		if (uf->o.type != UNIT_ORNITHOPTER) {
			if ((uf->o.seenByHouses & (1 << s->o.houseID)) == 0) continue;
		}

		distance = Tile_GetDistance(uf->o.position, s->o.position);
		if (distance >= distanceCurrent) continue;

		if (uf->o.type == UNIT_ORNITHOPTER) {
			if (distance >= targetRange * 3) continue;
		} else {
			if (distance >= targetRange) continue;
		}

		/* ENHANCEMENT -- The original code swapped the assignment, making it do nothing, Now it finds the closest unit to shoot at, what seems to be the intention */
		if (g_dune2_enhanced) distanceCurrent = distance;
		u = uf;
	}

	if (u == NULL) return IT_NONE;
	return Tools_Index_Encode(u->o.index, IT_UNIT);
}
Beispiel #6
0
/**
 * Fire a bullet or missile from a (rocket) turret.
 *
 * Stack: *none*
 * Variables: 2 - Target to shoot at.
 *
 * @param script The script engine to operate on.
 * @return The time between this and the next time firing.
 */
uint16 Script_Structure_Fire(ScriptEngine *script)
{
	Structure *s;
	Unit *u;
	tile32 position;
	uint16 target;
	uint16 damage;
	uint16 fireDelay;
	uint16 type;

	s = g_scriptCurrentStructure;

	target = script->variables[2];
	if (target == 0) return 0;

	if (s->o.type == STRUCTURE_ROCKET_TURRET && Tile_GetDistance(Tools_Index_GetTile(target), s->o.position) >= 0x300) {
		type      = UNIT_MISSILE_TURRET;
		damage    = 30;
		fireDelay = Tools_AdjustToGameSpeed(g_table_unitInfo[UNIT_LAUNCHER].fireDelay, 1, 255, true);
	} else {
		type      = UNIT_BULLET;
		damage    = 20;
		fireDelay = Tools_AdjustToGameSpeed(g_table_unitInfo[UNIT_TANK].fireDelay, 1, 255, true);
	}

	position.tile = s->o.position.tile;
	position.s.x += 0x80;
	position.s.y += 0x80;
	u = Unit_CreateBullet(position, type, s->o.houseID, damage, target);

	if (u == NULL) return 0;

	u->originEncoded = Tools_Index_Encode(s->o.index, IT_STRUCTURE);

	return fireDelay;
}
Beispiel #7
0
/**
 * Calculates the rounded up distance between the two given packed tiles.
 *
 * @param from The origin.
 * @param to The destination.
 * @return The longest distance between the X or Y coordinates, plus half the shortest.
 */
uint16 Tile_GetDistanceRoundedUp(tile32 from, tile32 to)
{
    return (Tile_GetDistance(from, to) + 0x80) >> 8;
}