/** * Unknown function 0543. * * Stack: 1 - A distance. * * @param script The script engine to operate on. * @return The number of moving units. */ uint16 Script_Team_Unknown0543(ScriptEngine *script) { Team *t; uint16 count = 0; uint16 distance; PoolFindStruct find; t = g_scriptCurrentTeam; distance = STACK_PEEK(1); find.houseID = t->houseID; find.index = 0xFFFF; find.type = 0xFFFF; while (true) { Unit *u; tile32 tile; uint16 distanceUnitDest; uint16 distanceUnitTeam; uint16 distanceTeamDest; u = Unit_Find(&find); if (u == NULL) break; if (t->index != u->team - 1) continue; tile = Tools_Index_GetTile(u->targetMove); distanceUnitTeam = Tile_GetDistanceRoundedUp(u->o.position, t->position); if (u->targetMove != 0) { distanceUnitDest = Tile_GetDistanceRoundedUp(u->o.position, tile); distanceTeamDest = Tile_GetDistanceRoundedUp(t->position, tile); } else { distanceUnitDest = 64; distanceTeamDest = 64; } if ((distanceUnitDest < distanceTeamDest && (distance + 2) < distanceUnitTeam) || (distanceUnitDest >= distanceTeamDest && distanceUnitTeam > distance)) { Unit_SetAction(u, ACTION_MOVE); tile = Tile_MoveByRandom(t->position, distance << 4, true); Unit_SetDestination(u, Tools_Index_Encode(Tile_PackTile(tile), IT_TILE)); count++; continue; } Unit_SetAction(u, ACTION_GUARD); } return count; }
/** * 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); } } }
/** * Gets the average distance between current team members, and set the * position of the team to the average position. * * Stack: *none*. * * @param script The script engine to operate on. * @return The average distance. */ uint16 Script_Team_GetAverageDistance(ScriptEngine *script) { uint16 averageX = 0; uint16 averageY = 0; uint16 count = 0; uint16 distance = 0; Team *t; PoolFindStruct find; VARIABLE_NOT_USED(script); t = g_scriptCurrentTeam; find.houseID = t->houseID; find.index = 0xFFFF; find.type = 0xFFFF; while (true) { Unit *u; u = Unit_Find(&find); if (u == NULL) break; if (t->index != u->team - 1) continue; count++; averageX += (u->o.position.x >> 8) & 0x3f; averageY += (u->o.position.y >> 8) & 0x3f; } if (count == 0) return 0; averageX /= count; averageY /= count; t->position = Tile_MakeXY(averageX, averageY); find.houseID = t->houseID; find.index = 0xFFFF; find.type = 0xFFFF; while (true) { Unit *u; u = Unit_Find(&find); if (u == NULL) break; if (t->index != u->team - 1) continue; distance += Tile_GetDistanceRoundedUp(u->o.position, t->position); } distance /= count; if (t->target == 0 || t->targetTile == 0) return distance; if (Tile_GetDistancePacked(Tile_PackXY(averageX, averageY), Tools_Index_GetPackedTile(t->target)) <= 10) t->targetTile = 2; return distance; }
/** * Makes the current unit to go to the closest structure of the given type. * * Stack: 1 - The type of the structure. * * @param script The script engine to operate on. * @return The value 1 if and only if a structure has been found. */ uint16 Script_Unit_GoToClosestStructure(ScriptEngine *script) { Unit *u; Structure *s = NULL; PoolFindStruct find; uint16 distanceMin =0; u = g_scriptCurrentUnit; find.houseID = Unit_GetHouseID(u); find.index = 0xFFFF; find.type = STACK_PEEK(1); while (true) { Structure *s2; uint16 distance; s2 = Structure_Find(&find); if (s2 == NULL) break; if (s2->state != STRUCTURE_STATE_IDLE) continue; if (s2->o.linkedID != 0xFF) continue; if (s2->o.script.variables[4] != 0) continue; distance = Tile_GetDistanceRoundedUp(s2->o.position, u->o.position); if (distance >= distanceMin && distanceMin != 0) continue; distanceMin = distance; s = s2; } if (s == NULL) return 0; Unit_SetAction(u, ACTION_MOVE); Unit_SetDestination(u, Tools_Index_Encode(s->o.index, IT_STRUCTURE)); return 1; }
/** * Pickup a unit (either from structure or on the map). The unit that does the * picking up returns the unit to his last position. * * Stack: *none*. * * @param script The script engine to operate on. * @return The value 0. Always. */ uint16 Script_Unit_Pickup(ScriptEngine *script) { Unit *u; VARIABLE_NOT_USED(script); u = g_scriptCurrentUnit; if (u->o.linkedID != 0xFF) return 0; switch (Tools_Index_GetType(u->targetMove)) { case IT_STRUCTURE: { Structure *s; Unit *u2; s = Tools_Index_GetStructure(u->targetMove); /* There was nothing to pickup here */ if (s->state != STRUCTURE_STATE_READY) { Object_Script_Variable4_Clear(&u->o); u->targetMove = 0; return 0; } u->o.flags.s.inTransport = true; Object_Script_Variable4_Clear(&u->o); u->targetMove = 0; u2 = Unit_Get_ByIndex(s->o.linkedID); /* Pickup the unit */ u->o.linkedID = u2->o.index & 0xFF; s->o.linkedID = u2->o.linkedID; u2->o.linkedID = 0xFF; if (s->o.linkedID == 0xFF) Structure_SetState(s, STRUCTURE_STATE_IDLE); /* Check if the unit has a return-to position or try to find spice in case of a harvester */ if (u2->targetLast.tile != 0) { u->targetMove = Tools_Index_Encode(Tile_PackTile(u2->targetLast), IT_TILE); } else if (u2->o.type == UNIT_HARVESTER && Unit_GetHouseID(u2) != g_playerHouseID) { u->targetMove = Tools_Index_Encode(Map_SearchSpice(Tile_PackTile(u->o.position), 20), IT_TILE); } Unit_UpdateMap(2, u); return 1; } case IT_UNIT: { Unit *u2; Structure *s = NULL; PoolFindStruct find; int16 minDistance = 0; u2 = Tools_Index_GetUnit(u->targetMove); if (!u2->o.flags.s.allocated) return 0; find.houseID = Unit_GetHouseID(u); find.index = 0xFFFF; find.type = 0xFFFF; /* Find closest refinery / repair station */ while (true) { Structure *s2; int16 distance; s2 = Structure_Find(&find); if (s2 == NULL) break; distance = Tile_GetDistanceRoundedUp(s2->o.position, u->o.position); if (u2->o.type == UNIT_HARVESTER) { if (s2->o.type != STRUCTURE_REFINERY || s2->state != STRUCTURE_STATE_IDLE || s2->o.script.variables[4] != 0) continue; if (minDistance != 0 && distance >= minDistance) break; minDistance = distance; s = s2; break; } if (s2->o.type != STRUCTURE_REPAIR || s2->state != STRUCTURE_STATE_IDLE || s2->o.script.variables[4] != 0) continue; if (minDistance != 0 && distance >= minDistance) continue; minDistance = distance; s = s2; } if (s == NULL) return 0; /* Deselect the unit as it is about to be picked up */ if (u2 == g_unitSelected) Unit_Select(NULL); /* Pickup the unit */ u->o.linkedID = u2->o.index & 0xFF; u->o.flags.s.inTransport = true; Unit_UpdateMap(0, u2); Unit_Hide(u2); /* Set where we are going to */ Object_Script_Variable4_Link(Tools_Index_Encode(u->o.index, IT_UNIT), Tools_Index_Encode(s->o.index, IT_STRUCTURE)); u->targetMove = u->o.script.variables[4]; Unit_UpdateMap(2, u); if (u2->o.type != UNIT_HARVESTER) return 0; /* Check if we want to return to this spice field later */ if (Map_SearchSpice(Tile_PackTile(u2->o.position), 2) == 0) { u2->targetPreLast.tile = 0; u2->targetLast.tile = 0; } return 0; } default: return 0; } }