1514 } |
1514 } |
1515 |
1515 |
1516 return ret; |
1516 return ret; |
1517 } |
1517 } |
1518 |
1518 |
1519 static void GetFSMportsLayout(byte *layout, int width, int length, const FSMportsSpec *fsmportspec) |
1519 static void GetFSMportsLayout(byte *layout, int width, int length, const FSMportsSpec *fsmportspec, byte set) |
1520 { |
1520 { |
1521 if (fsmportspec != NULL) { |
1521 if (fsmportspec != NULL) { |
1522 /* Custom layout defined, follow it. */ |
1522 /* Custom layout defined, follow it. */ |
1523 memcpy(layout, fsmportspec->layouts[width - 1][length - 1], |
1523 memcpy(layout, fsmportspec->layouts[set], |
1524 length * width); |
1524 (length * width) + 2); // width*length sprites, plus orientation byte, and preview minipic sprite |
1525 return; |
1525 return; |
1526 } |
1526 } |
1527 |
1527 |
1528 while (--width >= 0) { |
1528 while (--width >= 0) { |
1529 layout = CreateMulti(layout, length, 4); |
1529 layout = CreateMulti(layout, length, 4); |
1533 |
1533 |
1534 /** Place an Airport. |
1534 /** Place an Airport. |
1535 * @param tile tile where airport will be built |
1535 * @param tile tile where airport will be built |
1536 * @param flags operation to perform |
1536 * @param flags operation to perform |
1537 * @param p1 various bitstuffed elements |
1537 * @param p1 various bitstuffed elements |
1538 * - p1 = (bit 0) - orientation (Axis) |
1538 * - p1 = (bit 0-2) - layout_set for newgrf |
1539 * - p1 = (bit 8-15) - length |
1539 * - p1 = (bit 8-15) - length |
1540 * - p1 = (bit 16-23) - width |
1540 * - p1 = (bit 16-23) - width |
1541 * - p1 = (bit 24) - allow stations directly adjacent to other stations. |
1541 * - p1 = (bit 24) - allow stations directly adjacent to other stations. |
1542 * @param p2 various bitstuffed elements |
1542 * @param p2 various bitstuffed elements |
1543 * - p2 = (bit 0- 3) - airport type |
1543 * - p2 = (bit 0- 3) - airport type |
1549 { |
1549 { |
1550 bool airport_upgrade = true; |
1550 bool airport_upgrade = true; |
1551 const uint airport_type_for_flat_check = 0x80 | (GB(p2, 0, 4) << 3); |
1551 const uint airport_type_for_flat_check = 0x80 | (GB(p2, 0, 4) << 3); |
1552 bool newfsmairport = (HASBIT(p2, 7)); |
1552 bool newfsmairport = (HASBIT(p2, 7)); |
1553 byte original_airport_type = GB(p2, 0, 4); |
1553 byte original_airport_type = GB(p2, 0, 4); |
|
1554 byte layout_set = GB(p1, 0, 3); |
1554 |
1555 |
1555 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
1556 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
1556 |
1557 |
1557 /* Check if a valid, buildable airport was chosen for construction */ |
1558 /* Check if a valid, buildable airport was chosen for construction */ |
1558 //if (p1 > lengthof(_airport_sections) || !HASBIT(GetValidAirports(), p1)) return CMD_ERROR; |
1559 //if (p1 > lengthof(_airport_sections) || !HASBIT(GetValidAirports(), p1)) return CMD_ERROR; |
1575 return_cmd_error(STR_2035_LOCAL_AUTHORITY_REFUSES); |
1576 return_cmd_error(STR_2035_LOCAL_AUTHORITY_REFUSES); |
1576 } |
1577 } |
1577 } |
1578 } |
1578 |
1579 |
1579 const AirportFTAClass *afc = GetAirport(original_airport_type); |
1580 const AirportFTAClass *afc = GetAirport(original_airport_type); |
1580 int w = afc->size_x; |
1581 byte w = afc->size_x; |
1581 int h = afc->size_y; |
1582 byte h = afc->size_y; |
1582 |
1583 |
1583 Station *st = NULL; |
1584 Station *st = NULL; |
1584 |
1585 |
1585 /* Check if the given station class is valid */ |
1586 /* Check if the given station class is valid */ |
1586 if (GB(p2, 8, 8) >= FSMPORTS_CLASS_MAX) return CMD_ERROR; |
1587 if (GB(p2, 8, 8) >= FSMPORTS_CLASS_MAX) return CMD_ERROR; |
1588 /* Check if we can allocate a custom stationspec to this station */ |
1589 /* Check if we can allocate a custom stationspec to this station */ |
1589 const FSMportsSpec *fsmportsspec = GetCustomFSMportsSpec((FSMportsClassID)GB(p2, 8, 8), GB(p2, 16, 8)); |
1590 const FSMportsSpec *fsmportsspec = GetCustomFSMportsSpec((FSMportsClassID)GB(p2, 8, 8), GB(p2, 16, 8)); |
1590 |
1591 |
1591 if (newfsmairport) { |
1592 if (newfsmairport) { |
1592 /* Perform NewStation checks */ |
1593 /* Perform NewStation checks */ |
1593 w = fsmportsspec->width; |
1594 w = fsmportsspec->size_x[layout_set]; |
1594 h = fsmportsspec->lengths; |
1595 h = fsmportsspec->size_y[layout_set]; |
1595 |
1596 |
1596 /* Check if the station is buildable */ |
1597 /* Check if the station is buildable */ |
1597 if (HASBIT(fsmportsspec->callbackmask, CBM_STATION_AVAIL) && GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportsspec, NULL, INVALID_TILE) == 0) { |
1598 if (HASBIT(fsmportsspec->callbackmask, CBM_STATION_AVAIL) && GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportsspec, NULL, INVALID_TILE) == 0) { |
1598 return CMD_ERROR; |
1599 return CMD_ERROR; |
1599 } |
1600 } |
1663 |
1664 |
1664 st->airport_tile = tile; |
1665 st->airport_tile = tile; |
1665 st->AddFacility(FACIL_AIRPORT, tile); |
1666 st->AddFacility(FACIL_AIRPORT, tile); |
1666 st->airport_type = (byte)original_airport_type; |
1667 st->airport_type = (byte)original_airport_type; |
1667 st->airport_flags.ResetAll(); |
1668 st->airport_flags.ResetAll(); |
|
1669 st->FSMport_layout_set = layout_set; |
1668 |
1670 |
1669 st->rect.BeforeAddRect(tile, w, h, StationRect::ADD_TRY); |
1671 st->rect.BeforeAddRect(tile, w, h, StationRect::ADD_TRY); |
1670 |
1672 |
1671 /* if airport was demolished while planes were en-route to it, the |
1673 /* if airport was demolished while planes were en-route to it, the |
1672 * positions can no longer be the same (v->u.air.pos), since different |
1674 * positions can no longer be the same (v->u.air.pos), since different |
1679 |
1681 |
1680 if (newfsmairport) { |
1682 if (newfsmairport) { |
1681 fsmportspecindex = AllocateFSMportsSpecToStation(fsmportsspec, st, flags & DC_EXEC); |
1683 fsmportspecindex = AllocateFSMportsSpecToStation(fsmportsspec, st, flags & DC_EXEC); |
1682 if (fsmportspecindex == -1) return CMD_ERROR; |
1684 if (fsmportspecindex == -1) return CMD_ERROR; |
1683 |
1685 |
1684 layout_ptr = (byte*)alloca(w * h); |
1686 layout_ptr = (byte*)alloca((w * h) + 2); |
1685 GetFSMportsLayout(layout_ptr, w, h, fsmportsspec); |
1687 GetFSMportsLayout(layout_ptr, w, h, fsmportsspec, layout_set); |
|
1688 layout_ptr++; //skip orientation |
|
1689 layout_ptr++; //skip minipic ID |
1686 } else { |
1690 } else { |
1687 layout_ptr = (byte*)_airport_sections[original_airport_type]; |
1691 layout_ptr = (byte*)_airport_sections[original_airport_type]; |
1688 } |
1692 } |
1689 |
1693 |
1690 { |
1694 { |
1711 static CommandCost RemoveAirport(Station *st, uint32 flags) |
1715 static CommandCost RemoveAirport(Station *st, uint32 flags) |
1712 { |
1716 { |
1713 int w, h; |
1717 int w, h; |
1714 const FSMportsSpec *fsmportsspec; |
1718 const FSMportsSpec *fsmportsspec; |
1715 const AirportFTAClass *afc; |
1719 const AirportFTAClass *afc; |
|
1720 byte layout_set = st->FSMport_layout_set; |
1716 |
1721 |
1717 if (_current_player != OWNER_WATER && !CheckOwnership(st->owner)) |
1722 if (_current_player != OWNER_WATER && !CheckOwnership(st->owner)) |
1718 return CMD_ERROR; |
1723 return CMD_ERROR; |
1719 |
1724 |
1720 TileIndex tile = st->airport_tile; |
1725 TileIndex tile = st->airport_tile; |
1721 bool newfsmairport = IsCustomFSMportsSpecIndex(tile); |
1726 bool newfsmairport = IsCustomFSMportsSpecIndex(tile); |
1722 |
1727 |
1723 if (newfsmairport) { |
1728 if (newfsmairport) { |
1724 fsmportsspec = st->fsmportsspeclist[GetCustomStationSpecIndex(tile)].spec; |
1729 fsmportsspec = st->fsmportsspeclist[GetCustomStationSpecIndex(tile)].spec; |
1725 w = fsmportsspec->width; |
1730 w = fsmportsspec->size_x[layout_set]; |
1726 h = fsmportsspec->lengths; |
1731 h = fsmportsspec->size_y[layout_set]; |
1727 } else { |
1732 } else { |
1728 afc = st->Airport(); |
1733 afc = st->Airport(); |
1729 w = afc->size_x; |
1734 w = afc->size_x; |
1730 h = afc->size_y; |
1735 h = afc->size_y; |
1731 } |
1736 } |
1741 |
1746 |
1742 byte *layout_ptr; |
1747 byte *layout_ptr; |
1743 byte layout; |
1748 byte layout; |
1744 |
1749 |
1745 if (newfsmairport) { |
1750 if (newfsmairport) { |
1746 layout_ptr = (byte*)alloca(w * h); |
1751 layout_ptr = (byte*)alloca((w * h) + 2); |
1747 GetFSMportsLayout(layout_ptr, w, h, fsmportsspec); |
1752 GetFSMportsLayout(layout_ptr, w, h, fsmportsspec, layout_set); |
|
1753 layout_ptr++; //skip orientation |
|
1754 layout_ptr++; //skip minipic ID |
1748 } else { |
1755 } else { |
1749 layout_ptr = (byte*)_airport_sections[st->airport_type]; |
1756 layout_ptr = (byte*)_airport_sections[st->airport_type]; |
1750 } |
1757 } |
1751 |
1758 |
1752 { |
1759 { |