mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Reformat all sources.
parent
928a388a65
commit
0859d0393e
|
@ -137,6 +137,7 @@ public:
|
|||
/** Wrapper function for AIScanner::HasAI */
|
||||
static bool HasAI(const ContentInfo &ci, bool md5sum);
|
||||
static bool HasAILibrary(const ContentInfo &ci, bool md5sum);
|
||||
|
||||
private:
|
||||
static uint frame_counter; ///< Tick counter for the AI code
|
||||
static std::unique_ptr<AIScannerInfo> scanner_info; ///< ScriptScanner instance that is used to find AIs
|
||||
|
|
|
@ -8,11 +8,13 @@
|
|||
/** @file ai_config.cpp Implementation of AIConfig. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "ai_config.hpp"
|
||||
|
||||
#include "../company_base.h"
|
||||
#include "../settings_type.h"
|
||||
#include "../string_func.h"
|
||||
#include "ai.hpp"
|
||||
#include "ai_config.hpp"
|
||||
#include "ai_info.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
#ifndef AI_CONFIG_HPP
|
||||
#define AI_CONFIG_HPP
|
||||
|
||||
#include "../script/script_config.hpp"
|
||||
#include "../company_type.h"
|
||||
#include "../script/script_config.hpp"
|
||||
|
||||
class AIConfig : public ScriptConfig {
|
||||
public:
|
||||
|
@ -20,13 +20,9 @@ public:
|
|||
*/
|
||||
static AIConfig *GetConfig(CompanyID company, ScriptSettingSource source = SSS_DEFAULT);
|
||||
|
||||
AIConfig() :
|
||||
ScriptConfig()
|
||||
{}
|
||||
AIConfig() : ScriptConfig() {}
|
||||
|
||||
AIConfig(const AIConfig &config) :
|
||||
ScriptConfig(config)
|
||||
{}
|
||||
AIConfig(const AIConfig &config) : ScriptConfig(config) {}
|
||||
|
||||
class AIInfo *GetInfo() const;
|
||||
|
||||
|
|
|
@ -8,18 +8,19 @@
|
|||
/** @file ai_core.cpp Implementation of AI. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "../core/backup_type.hpp"
|
||||
#include "../core/bitmath_func.hpp"
|
||||
#include "../company_base.h"
|
||||
#include "../company_func.h"
|
||||
#include "../framerate_type.h"
|
||||
#include "../network/network.h"
|
||||
#include "../window_func.h"
|
||||
#include "../framerate_type.h"
|
||||
#include "ai_scanner.hpp"
|
||||
#include "ai_instance.hpp"
|
||||
#include "ai.hpp"
|
||||
#include "ai_config.hpp"
|
||||
#include "ai_info.hpp"
|
||||
#include "ai.hpp"
|
||||
#include "ai_instance.hpp"
|
||||
#include "ai_scanner.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
|
@ -292,7 +293,7 @@
|
|||
|
||||
/* static */ void AI::GetConsoleLibraryList(std::back_insert_iterator<std::string> &output_iterator)
|
||||
{
|
||||
AI::scanner_library->GetConsoleList(output_iterator, true);
|
||||
AI::scanner_library->GetConsoleList(output_iterator, true);
|
||||
}
|
||||
|
||||
/* static */ const ScriptInfoList *AI::GetInfoList()
|
||||
|
@ -353,4 +354,3 @@
|
|||
{
|
||||
return AI::scanner_library.get();
|
||||
}
|
||||
|
||||
|
|
|
@ -8,25 +8,25 @@
|
|||
/** @file ai_gui.cpp %Window for configuring the AIs */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../error.h"
|
||||
#include "../company_base.h"
|
||||
#include "../window_func.h"
|
||||
#include "../network/network.h"
|
||||
#include "../settings_func.h"
|
||||
#include "../network/network_content.h"
|
||||
#include "../core/geometry_func.hpp"
|
||||
|
||||
#include "ai.hpp"
|
||||
#include "ai_gui.hpp"
|
||||
|
||||
#include "../core/geometry_func.hpp"
|
||||
#include "../company_base.h"
|
||||
#include "../error.h"
|
||||
#include "../network/network.h"
|
||||
#include "../network/network_content.h"
|
||||
#include "../script/script_gui.h"
|
||||
#include "../settings_func.h"
|
||||
#include "../window_func.h"
|
||||
#include "ai.hpp"
|
||||
#include "ai_config.hpp"
|
||||
#include "ai_info.hpp"
|
||||
#include "../script/script_gui.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
|
||||
/** Widgets for the configure AI window. */
|
||||
/* clang-format off */
|
||||
static constexpr NWidgetPart _nested_ai_config_widgets[] = {
|
||||
|
@ -85,12 +85,7 @@ static constexpr NWidgetPart _nested_ai_config_widgets[] = {
|
|||
/* clang-format on */
|
||||
|
||||
/** Window definition for the configure AI window. */
|
||||
static WindowDesc _ai_config_desc(
|
||||
WDP_CENTER, nullptr, 0, 0,
|
||||
WC_GAME_OPTIONS, WC_NONE,
|
||||
{},
|
||||
_nested_ai_config_widgets
|
||||
);
|
||||
static WindowDesc _ai_config_desc(WDP_CENTER, nullptr, 0, 0, WC_GAME_OPTIONS, WC_NONE, {}, _nested_ai_config_widgets);
|
||||
|
||||
/**
|
||||
* Window to configure which AIs will start.
|
||||
|
@ -283,7 +278,7 @@ struct AIConfigWindow : public Window {
|
|||
break;
|
||||
}
|
||||
|
||||
case WID_AIC_CHANGE: // choose other AI
|
||||
case WID_AIC_CHANGE: // choose other AI
|
||||
if (IsEditable(this->selected_slot)) ShowScriptListWindow((CompanyID)this->selected_slot, _ctrl_pressed);
|
||||
break;
|
||||
|
||||
|
@ -338,4 +333,3 @@ void ShowAIConfigWindow()
|
|||
CloseWindowByClass(WC_GAME_OPTIONS);
|
||||
new AIConfigWindow();
|
||||
}
|
||||
|
||||
|
|
|
@ -9,12 +9,13 @@
|
|||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "../script/squirrel_class.hpp"
|
||||
#include "ai_info.hpp"
|
||||
#include "ai_scanner.hpp"
|
||||
|
||||
#include "../debug.h"
|
||||
#include "../string_func.h"
|
||||
#include "../rev.h"
|
||||
#include "../script/squirrel_class.hpp"
|
||||
#include "../string_func.h"
|
||||
#include "ai_scanner.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
|
@ -27,7 +28,12 @@ static bool CheckAPIVersion(const std::string &api_version)
|
|||
return std::ranges::find(AIInfo::ApiVersions, api_version) != std::end(AIInfo::ApiVersions);
|
||||
}
|
||||
|
||||
template <> SQInteger PushClassName<AIInfo, ScriptType::AI>(HSQUIRRELVM vm) { sq_pushstring(vm, "AIInfo", -1); return 1; }
|
||||
template <>
|
||||
SQInteger PushClassName<AIInfo, ScriptType::AI>(HSQUIRRELVM vm)
|
||||
{
|
||||
sq_pushstring(vm, "AIInfo", -1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* static */ void AIInfo::RegisterAPI(Squirrel *engine)
|
||||
{
|
||||
|
@ -111,11 +117,7 @@ template <> SQInteger PushClassName<AIInfo, ScriptType::AI>(HSQUIRRELVM vm) { sq
|
|||
return 0;
|
||||
}
|
||||
|
||||
AIInfo::AIInfo() :
|
||||
min_loadable_version(0),
|
||||
use_as_random(false)
|
||||
{
|
||||
}
|
||||
AIInfo::AIInfo() : min_loadable_version(0), use_as_random(false) {}
|
||||
|
||||
bool AIInfo::CanLoadFromVersion(int version) const
|
||||
{
|
||||
|
@ -123,7 +125,6 @@ bool AIInfo::CanLoadFromVersion(int version) const
|
|||
return version >= this->min_loadable_version && version <= this->GetVersion();
|
||||
}
|
||||
|
||||
|
||||
/* static */ void AILibrary::RegisterAPI(Squirrel *engine)
|
||||
{
|
||||
/* Create the AILibrary class, and add the RegisterLibrary function */
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
class AIInfo : public ScriptInfo {
|
||||
public:
|
||||
/* All valid AI API versions, in order. */
|
||||
static constexpr std::string_view ApiVersions[]{ "0.7", "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "1.10", "1.11", "12", "13", "14", "15" };
|
||||
static constexpr std::string_view ApiVersions[]{"0.7", "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "1.10", "1.11", "12", "13", "14", "15"};
|
||||
|
||||
AIInfo();
|
||||
|
||||
|
@ -43,17 +43,23 @@ public:
|
|||
/**
|
||||
* Use this AI as a random AI.
|
||||
*/
|
||||
bool UseAsRandomAI() const { return this->use_as_random; }
|
||||
bool UseAsRandomAI() const
|
||||
{
|
||||
return this->use_as_random;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the API version this AI is written for.
|
||||
*/
|
||||
const std::string &GetAPIVersion() const { return this->api_version; }
|
||||
const std::string &GetAPIVersion() const
|
||||
{
|
||||
return this->api_version;
|
||||
}
|
||||
|
||||
private:
|
||||
int min_loadable_version; ///< The AI can load savegame data if the version is equal or greater than this.
|
||||
bool use_as_random; ///< Should this AI be used when the user wants a "random AI"?
|
||||
std::string api_version; ///< API version used by this AI.
|
||||
bool use_as_random; ///< Should this AI be used when the user wants a "random AI"?
|
||||
std::string api_version; ///< API version used by this AI.
|
||||
};
|
||||
|
||||
/** All static information from an AI library like name, version, etc. */
|
||||
|
@ -74,7 +80,10 @@ public:
|
|||
/**
|
||||
* Get the category this library is in.
|
||||
*/
|
||||
const std::string &GetCategory() const { return this->category; }
|
||||
const std::string &GetCategory() const
|
||||
{
|
||||
return this->category;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string category; ///< The category this library is in.
|
||||
|
|
|
@ -8,21 +8,20 @@
|
|||
/** @file ai_instance.cpp Implementation of AIInstance. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../debug.h"
|
||||
#include "../error.h"
|
||||
|
||||
#include "ai_instance.hpp"
|
||||
|
||||
#include "../company_base.h"
|
||||
#include "../company_func.h"
|
||||
|
||||
#include "../script/squirrel_class.hpp"
|
||||
|
||||
#include "ai_config.hpp"
|
||||
#include "ai.hpp"
|
||||
|
||||
#include "../script/script_storage.hpp"
|
||||
#include "../debug.h"
|
||||
#include "../error.h"
|
||||
#include "../script/script_cmd.h"
|
||||
#include "../script/script_gui.h"
|
||||
#include "../script/script_storage.hpp"
|
||||
#include "../script/squirrel_class.hpp"
|
||||
#include "ai.hpp"
|
||||
#include "ai_config.hpp"
|
||||
#include "ai_info.hpp"
|
||||
#include "ai_instance.hpp"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
|
@ -34,9 +33,7 @@
|
|||
|
||||
#include "../safeguards.h"
|
||||
|
||||
AIInstance::AIInstance() :
|
||||
ScriptInstance("AI")
|
||||
{}
|
||||
AIInstance::AIInstance() : ScriptInstance("AI") {}
|
||||
|
||||
void AIInstance::Initialize(AIInfo *info)
|
||||
{
|
||||
|
|
|
@ -8,25 +8,22 @@
|
|||
/** @file ai_scanner.cpp allows scanning AI scripts */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "ai_scanner.hpp"
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "../core/random_func.hpp"
|
||||
#include "../debug.h"
|
||||
#include "../network/network.h"
|
||||
#include "../openttd.h"
|
||||
#include "../core/random_func.hpp"
|
||||
|
||||
#include "../script/squirrel_class.hpp"
|
||||
#include "../script/api/script_object.hpp"
|
||||
#include "../script/squirrel_class.hpp"
|
||||
#include "ai_info.hpp"
|
||||
#include "ai_scanner.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
|
||||
AIScannerInfo::AIScannerInfo() :
|
||||
ScriptScanner(),
|
||||
info_dummy(nullptr)
|
||||
{
|
||||
}
|
||||
AIScannerInfo::AIScannerInfo() : ScriptScanner(), info_dummy(nullptr) {}
|
||||
|
||||
void AIScannerInfo::Initialize()
|
||||
{
|
||||
|
@ -67,7 +64,9 @@ AIInfo *AIScannerInfo::SelectRandomAI() const
|
|||
}
|
||||
|
||||
/* Filter for AIs suitable as Random AI. */
|
||||
auto random_ais = info_single_list | std::views::filter([](const auto &item) { return static_cast<AIInfo *>(item.second)->UseAsRandomAI(); });
|
||||
auto random_ais = info_single_list | std::views::filter([](const auto &item) {
|
||||
return static_cast<AIInfo *>(item.second)->UseAsRandomAI();
|
||||
});
|
||||
|
||||
uint num_random_ais = std::ranges::distance(random_ais);
|
||||
if (num_random_ais == 0) {
|
||||
|
@ -119,7 +118,6 @@ AIInfo *AIScannerInfo::FindInfo(const std::string &name, int version, bool force
|
|||
return info;
|
||||
}
|
||||
|
||||
|
||||
void AIScannerLibrary::Initialize()
|
||||
{
|
||||
ScriptScanner::Initialize("AIScanner");
|
||||
|
|
|
@ -41,9 +41,22 @@ public:
|
|||
|
||||
protected:
|
||||
std::string GetScriptName(ScriptInfo *info) override;
|
||||
const char *GetFileName() const override { return PATHSEP "info.nut"; }
|
||||
Subdirectory GetDirectory() const override { return AI_DIR; }
|
||||
const char *GetScannerName() const override { return "AIs"; }
|
||||
|
||||
const char *GetFileName() const override
|
||||
{
|
||||
return PATHSEP "info.nut";
|
||||
}
|
||||
|
||||
Subdirectory GetDirectory() const override
|
||||
{
|
||||
return AI_DIR;
|
||||
}
|
||||
|
||||
const char *GetScannerName() const override
|
||||
{
|
||||
return "AIs";
|
||||
}
|
||||
|
||||
void RegisterAPI(class Squirrel *engine) override;
|
||||
|
||||
private:
|
||||
|
@ -64,9 +77,22 @@ public:
|
|||
|
||||
protected:
|
||||
std::string GetScriptName(ScriptInfo *info) override;
|
||||
const char *GetFileName() const override { return PATHSEP "library.nut"; }
|
||||
Subdirectory GetDirectory() const override { return AI_LIBRARY_DIR; }
|
||||
const char *GetScannerName() const override { return "AI Libraries"; }
|
||||
|
||||
const char *GetFileName() const override
|
||||
{
|
||||
return PATHSEP "library.nut";
|
||||
}
|
||||
|
||||
Subdirectory GetDirectory() const override
|
||||
{
|
||||
return AI_LIBRARY_DIR;
|
||||
}
|
||||
|
||||
const char *GetScannerName() const override
|
||||
{
|
||||
return "AI Libraries";
|
||||
}
|
||||
|
||||
void RegisterAPI(class Squirrel *engine) override;
|
||||
};
|
||||
|
||||
|
|
|
@ -27,14 +27,14 @@ struct Aircraft;
|
|||
/** An aircraft can be one of those types. */
|
||||
enum AircraftSubType : uint8_t {
|
||||
AIR_HELICOPTER = 0, ///< an helicopter
|
||||
AIR_AIRCRAFT = 2, ///< an airplane
|
||||
AIR_SHADOW = 4, ///< shadow of the aircraft
|
||||
AIR_ROTOR = 6, ///< rotor of an helicopter
|
||||
AIR_AIRCRAFT = 2, ///< an airplane
|
||||
AIR_SHADOW = 4, ///< shadow of the aircraft
|
||||
AIR_ROTOR = 6, ///< rotor of an helicopter
|
||||
};
|
||||
|
||||
/** Flags for air vehicles; shared with disaster vehicles. */
|
||||
enum AirVehicleFlags : uint8_t {
|
||||
VAF_DEST_TOO_FAR = 0, ///< Next destination is too far away.
|
||||
VAF_DEST_TOO_FAR = 0, ///< Next destination is too far away.
|
||||
|
||||
/* The next two flags are to prevent stair climbing of the aircraft. The idea is that the aircraft
|
||||
* will ascend or descend multiple flight levels at a time instead of following the contours of the
|
||||
|
@ -42,10 +42,10 @@ enum AirVehicleFlags : uint8_t {
|
|||
VAF_IN_MAX_HEIGHT_CORRECTION = 1, ///< The vehicle is currently lowering its altitude because it hit the upper bound.
|
||||
VAF_IN_MIN_HEIGHT_CORRECTION = 2, ///< The vehicle is currently raising its altitude because it hit the lower bound.
|
||||
|
||||
VAF_HELI_DIRECT_DESCENT = 3, ///< The helicopter is descending directly at its destination (helipad or in front of hangar)
|
||||
VAF_HELI_DIRECT_DESCENT = 3, ///< The helicopter is descending directly at its destination (helipad or in front of hangar)
|
||||
};
|
||||
|
||||
static const int ROTOR_Z_OFFSET = 5; ///< Z Offset between helicopter- and rotorsprite.
|
||||
static const int ROTOR_Z_OFFSET = 5; ///< Z Offset between helicopter- and rotorsprite.
|
||||
|
||||
void HandleAircraftEnterHangar(Aircraft *v);
|
||||
void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type);
|
||||
|
@ -84,18 +84,48 @@ struct Aircraft final : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
|
|||
|
||||
/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
|
||||
Aircraft() : SpecializedVehicleBase() {}
|
||||
|
||||
/** We want to 'destruct' the right class. */
|
||||
virtual ~Aircraft() { this->PreDestructor(); }
|
||||
virtual ~Aircraft()
|
||||
{
|
||||
this->PreDestructor();
|
||||
}
|
||||
|
||||
void MarkDirty() override;
|
||||
void UpdateDeltaXY() override;
|
||||
ExpensesType GetExpenseType(bool income) const override { return income ? EXPENSES_AIRCRAFT_REVENUE : EXPENSES_AIRCRAFT_RUN; }
|
||||
bool IsPrimaryVehicle() const override { return this->IsNormalAircraft(); }
|
||||
|
||||
ExpensesType GetExpenseType(bool income) const override
|
||||
{
|
||||
return income ? EXPENSES_AIRCRAFT_REVENUE : EXPENSES_AIRCRAFT_RUN;
|
||||
}
|
||||
|
||||
bool IsPrimaryVehicle() const override
|
||||
{
|
||||
return this->IsNormalAircraft();
|
||||
}
|
||||
|
||||
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const override;
|
||||
int GetDisplaySpeed() const override { return this->cur_speed; }
|
||||
int GetDisplayMaxSpeed() const override { return this->vcache.cached_max_speed; }
|
||||
int GetSpeedOldUnits() const { return this->vcache.cached_max_speed * 10 / 128; }
|
||||
int GetCurrentMaxSpeed() const override { return this->GetSpeedOldUnits(); }
|
||||
|
||||
int GetDisplaySpeed() const override
|
||||
{
|
||||
return this->cur_speed;
|
||||
}
|
||||
|
||||
int GetDisplayMaxSpeed() const override
|
||||
{
|
||||
return this->vcache.cached_max_speed;
|
||||
}
|
||||
|
||||
int GetSpeedOldUnits() const
|
||||
{
|
||||
return this->vcache.cached_max_speed * 10 / 128;
|
||||
}
|
||||
|
||||
int GetCurrentMaxSpeed() const override
|
||||
{
|
||||
return this->GetSpeedOldUnits();
|
||||
}
|
||||
|
||||
Money GetRunningCost() const override;
|
||||
|
||||
bool IsInDepot() const override
|
||||
|
@ -109,7 +139,12 @@ struct Aircraft final : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
|
|||
void OnNewEconomyDay() override;
|
||||
uint Crash(bool flooded = false) override;
|
||||
TileIndex GetOrderStationLocation(StationID station) override;
|
||||
TileIndex GetCargoTile() const override { return this->First()->tile; }
|
||||
|
||||
TileIndex GetCargoTile() const override
|
||||
{
|
||||
return this->First()->tile;
|
||||
}
|
||||
|
||||
ClosestDepot FindClosestDepot() override;
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,36 +11,38 @@
|
|||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "aircraft_cmd.h"
|
||||
|
||||
#include "core/backup_type.hpp"
|
||||
#include "core/random_func.hpp"
|
||||
#include "ai/ai.hpp"
|
||||
#include "aircraft.h"
|
||||
#include "cheat_type.h"
|
||||
#include "command_func.h"
|
||||
#include "company_base.h"
|
||||
#include "company_func.h"
|
||||
#include "disaster_vehicle.h"
|
||||
#include "effectvehicle_func.h"
|
||||
#include "engine_base.h"
|
||||
#include "error_func.h"
|
||||
#include "framerate_type.h"
|
||||
#include "game/game.hpp"
|
||||
#include "landscape.h"
|
||||
#include "news_func.h"
|
||||
#include "newgrf_airporttiles.h"
|
||||
#include "newgrf_engine.h"
|
||||
#include "newgrf_sound.h"
|
||||
#include "news_func.h"
|
||||
#include "sound_func.h"
|
||||
#include "spritecache.h"
|
||||
#include "error_func.h"
|
||||
#include "station_base.h"
|
||||
#include "strings_func.h"
|
||||
#include "command_func.h"
|
||||
#include "window_func.h"
|
||||
#include "timer/timer_game_calendar.h"
|
||||
#include "timer/timer_game_economy.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "sound_func.h"
|
||||
#include "cheat_type.h"
|
||||
#include "company_base.h"
|
||||
#include "ai/ai.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "company_func.h"
|
||||
#include "effectvehicle_func.h"
|
||||
#include "station_base.h"
|
||||
#include "engine_base.h"
|
||||
#include "core/random_func.hpp"
|
||||
#include "core/backup_type.hpp"
|
||||
#include "zoom_func.h"
|
||||
#include "disaster_vehicle.h"
|
||||
#include "newgrf_airporttiles.h"
|
||||
#include "framerate_type.h"
|
||||
#include "aircraft_cmd.h"
|
||||
#include "vehicle_cmd.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "window_func.h"
|
||||
#include "zoom_func.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
|
@ -54,12 +56,14 @@ void Aircraft::UpdateDeltaXY()
|
|||
this->y_extent = 2;
|
||||
|
||||
switch (this->subtype) {
|
||||
default: NOT_REACHED();
|
||||
default:
|
||||
NOT_REACHED();
|
||||
|
||||
case AIR_AIRCRAFT:
|
||||
case AIR_HELICOPTER:
|
||||
switch (this->state) {
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
case ENDTAKEOFF:
|
||||
case LANDING:
|
||||
case HELILANDING:
|
||||
|
@ -90,15 +94,8 @@ static bool AirportFindFreeTerminal(Aircraft *v, const AirportFTAClass *apc);
|
|||
static bool AirportFindFreeHelipad(Aircraft *v, const AirportFTAClass *apc);
|
||||
static void CrashAirplane(Aircraft *v);
|
||||
|
||||
static const SpriteID _aircraft_sprite[] = {
|
||||
0x0EB5, 0x0EBD, 0x0EC5, 0x0ECD,
|
||||
0x0ED5, 0x0EDD, 0x0E9D, 0x0EA5,
|
||||
0x0EAD, 0x0EE5, 0x0F05, 0x0F0D,
|
||||
0x0F15, 0x0F1D, 0x0F25, 0x0F2D,
|
||||
0x0EED, 0x0EF5, 0x0EFD, 0x0F35,
|
||||
0x0E9D, 0x0EA5, 0x0EAD, 0x0EB5,
|
||||
0x0EBD, 0x0EC5
|
||||
};
|
||||
static const SpriteID _aircraft_sprite[] = {0x0EB5, 0x0EBD, 0x0EC5, 0x0ECD, 0x0ED5, 0x0EDD, 0x0E9D, 0x0EA5, 0x0EAD, 0x0EE5, 0x0F05, 0x0F0D, 0x0F15, 0x0F1D, 0x0F25, 0x0F2D, 0x0EED, 0x0EF5, 0x0EFD,
|
||||
0x0F35, 0x0E9D, 0x0EA5, 0x0EAD, 0x0EB5, 0x0EBD, 0x0EC5};
|
||||
|
||||
template <>
|
||||
bool IsValidImageIndex<VEH_AIRCRAFT>(uint8_t image_index)
|
||||
|
@ -133,8 +130,7 @@ static StationID FindNearestHangar(const Aircraft *v)
|
|||
const Station *last_dest = nullptr;
|
||||
const Station *next_dest = nullptr;
|
||||
if (max_range != 0) {
|
||||
if (v->current_order.IsType(OT_GOTO_STATION) ||
|
||||
(v->current_order.IsType(OT_GOTO_DEPOT) && (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) == 0)) {
|
||||
if (v->current_order.IsType(OT_GOTO_STATION) || (v->current_order.IsType(OT_GOTO_DEPOT) && (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) == 0)) {
|
||||
last_dest = Station::GetIfValid(v->last_station_visited);
|
||||
next_dest = Station::GetIfValid(v->current_order.GetDestination().ToStationID());
|
||||
} else {
|
||||
|
@ -223,9 +219,7 @@ void DrawAircraftEngine(int left, int right, int preferred_x, int y, EngineID en
|
|||
|
||||
Rect rect;
|
||||
seq.GetBounds(&rect);
|
||||
preferred_x = Clamp(preferred_x,
|
||||
left - UnScaleGUI(rect.left),
|
||||
right - UnScaleGUI(rect.right));
|
||||
preferred_x = Clamp(preferred_x, left - UnScaleGUI(rect.left), right - UnScaleGUI(rect.right));
|
||||
|
||||
seq.Draw(preferred_x, y, pal, pal == PALETTE_CRASH);
|
||||
|
||||
|
@ -254,10 +248,10 @@ void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoff
|
|||
Rect rect;
|
||||
seq.GetBounds(&rect);
|
||||
|
||||
width = UnScaleGUI(rect.Width());
|
||||
width = UnScaleGUI(rect.Width());
|
||||
height = UnScaleGUI(rect.Height());
|
||||
xoffs = UnScaleGUI(rect.left);
|
||||
yoffs = UnScaleGUI(rect.top);
|
||||
xoffs = UnScaleGUI(rect.left);
|
||||
yoffs = UnScaleGUI(rect.top);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -395,7 +389,6 @@ CommandCost CmdBuildAircraft(DoCommandFlags flags, TileIndex tile, const Engine
|
|||
return CommandCost();
|
||||
}
|
||||
|
||||
|
||||
ClosestDepot Aircraft::FindClosestDepot()
|
||||
{
|
||||
const Station *st = GetTargetAirportIfValid(this);
|
||||
|
@ -593,7 +586,6 @@ static void PlayAircraftSound(const Vehicle *v)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update cached values of an aircraft.
|
||||
* Currently caches callback 36 max speed.
|
||||
|
@ -626,7 +618,6 @@ void UpdateAircraftCache(Aircraft *v, bool update_range)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Special velocities for aircraft
|
||||
*/
|
||||
|
@ -743,7 +734,8 @@ void GetAircraftFlightLevelBounds(const Vehicle *v, int *min_level, int *max_lev
|
|||
base_altitude += 10;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make faster planes fly higher so that they can overtake slower ones */
|
||||
|
@ -782,15 +774,13 @@ int GetAircraftFlightLevel(T *v, bool takeoff)
|
|||
assert(aircraft_middle_altitude < aircraft_max_altitude);
|
||||
|
||||
int z = v->z_pos;
|
||||
if (z < aircraft_min_altitude ||
|
||||
(HasBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION) && z < aircraft_middle_altitude)) {
|
||||
if (z < aircraft_min_altitude || (HasBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION) && z < aircraft_middle_altitude)) {
|
||||
/* Ascend. And don't fly into that mountain right ahead.
|
||||
* And avoid our aircraft become a stairclimber, so if we start
|
||||
* correcting altitude, then we stop correction not too early. */
|
||||
SetBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION);
|
||||
z += takeoff ? 2 : 1;
|
||||
} else if (!takeoff && (z > aircraft_max_altitude ||
|
||||
(HasBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION) && z > aircraft_middle_altitude))) {
|
||||
} else if (!takeoff && (z > aircraft_max_altitude || (HasBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION) && z > aircraft_middle_altitude))) {
|
||||
/* Descend lower. You are an aircraft, not an space ship.
|
||||
* And again, don't stop correcting altitude too early. */
|
||||
SetBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION);
|
||||
|
@ -854,7 +844,6 @@ static uint8_t AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *a
|
|||
return apc->entry_points[dir];
|
||||
}
|
||||
|
||||
|
||||
static void MaybeCrashAirplane(Aircraft *v);
|
||||
|
||||
/**
|
||||
|
@ -990,7 +979,7 @@ static bool AircraftController(Aircraft *v)
|
|||
}
|
||||
|
||||
/* Get distance from destination pos to current pos. */
|
||||
uint dist = abs(x + amd.x - v->x_pos) + abs(y + amd.y - v->y_pos);
|
||||
uint dist = abs(x + amd.x - v->x_pos) + abs(y + amd.y - v->y_pos);
|
||||
|
||||
/* Need exact position? */
|
||||
if (!amd.flags.Test(AirportMovingDataFlag::ExactPosition) && dist <= (amd.flags.Test(AirportMovingDataFlag::SlowTurn) ? 8U : 4U)) return true;
|
||||
|
@ -1024,9 +1013,18 @@ static bool AircraftController(Aircraft *v)
|
|||
bool hard_limit = true;
|
||||
|
||||
if (amd.flags.Test(AirportMovingDataFlag::NoSpeedClamp)) speed_limit = SPEED_LIMIT_NONE;
|
||||
if (amd.flags.Test(AirportMovingDataFlag::Hold)) { speed_limit = SPEED_LIMIT_HOLD; hard_limit = false; }
|
||||
if (amd.flags.Test(AirportMovingDataFlag::Land)) { speed_limit = SPEED_LIMIT_APPROACH; hard_limit = false; }
|
||||
if (amd.flags.Test(AirportMovingDataFlag::Brake)) { speed_limit = SPEED_LIMIT_TAXI; hard_limit = false; }
|
||||
if (amd.flags.Test(AirportMovingDataFlag::Hold)) {
|
||||
speed_limit = SPEED_LIMIT_HOLD;
|
||||
hard_limit = false;
|
||||
}
|
||||
if (amd.flags.Test(AirportMovingDataFlag::Land)) {
|
||||
speed_limit = SPEED_LIMIT_APPROACH;
|
||||
hard_limit = false;
|
||||
}
|
||||
if (amd.flags.Test(AirportMovingDataFlag::Brake)) {
|
||||
speed_limit = SPEED_LIMIT_TAXI;
|
||||
hard_limit = false;
|
||||
}
|
||||
|
||||
int count = UpdateAircraftSpeed(v, speed_limit, hard_limit);
|
||||
if (count == 0) return false;
|
||||
|
@ -1041,23 +1039,17 @@ static bool AircraftController(Aircraft *v)
|
|||
if (v->turn_counter != 0) v->turn_counter--;
|
||||
|
||||
do {
|
||||
|
||||
GetNewVehiclePosResult gp;
|
||||
|
||||
if (nudge_towards_target || amd.flags.Test(AirportMovingDataFlag::Land)) {
|
||||
/* move vehicle one pixel towards target */
|
||||
gp.x = (v->x_pos != (x + amd.x)) ?
|
||||
v->x_pos + ((x + amd.x > v->x_pos) ? 1 : -1) :
|
||||
v->x_pos;
|
||||
gp.y = (v->y_pos != (y + amd.y)) ?
|
||||
v->y_pos + ((y + amd.y > v->y_pos) ? 1 : -1) :
|
||||
v->y_pos;
|
||||
gp.x = (v->x_pos != (x + amd.x)) ? v->x_pos + ((x + amd.x > v->x_pos) ? 1 : -1) : v->x_pos;
|
||||
gp.y = (v->y_pos != (y + amd.y)) ? v->y_pos + ((y + amd.y > v->y_pos) ? 1 : -1) : v->y_pos;
|
||||
|
||||
/* Oilrigs must keep v->tile as st->airport.tile, since the landing pad is in a non-airport tile */
|
||||
gp.new_tile = (st->airport.type == AT_OILRIG) ? st->airport.tile : TileVirtXY(gp.x, gp.y);
|
||||
|
||||
} else {
|
||||
|
||||
/* Turn. Do it slowly if in the air. */
|
||||
Direction newdir = GetDirectionTowards(v, x + amd.x, y + amd.y);
|
||||
if (newdir != v->direction) {
|
||||
|
@ -1149,13 +1141,11 @@ static bool AircraftController(Aircraft *v)
|
|||
|
||||
/* We've landed. Decrease speed when we're reaching end of runway. */
|
||||
if (amd.flags.Test(AirportMovingDataFlag::Brake)) {
|
||||
|
||||
if (z > airport_z) {
|
||||
z--;
|
||||
} else if (z < airport_z) {
|
||||
z++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SetAircraftPosition(v, gp.x, gp.y, z);
|
||||
|
@ -1174,7 +1164,7 @@ static bool HandleCrashedAircraft(Aircraft *v)
|
|||
Station *st = GetTargetAirportIfValid(v);
|
||||
|
||||
/* make aircraft crash down to the ground */
|
||||
if (v->crashed_counter < 500 && st == nullptr && ((v->crashed_counter % 3) == 0) ) {
|
||||
if (v->crashed_counter < 500 && st == nullptr && ((v->crashed_counter % 3) == 0)) {
|
||||
int z = GetSlopePixelZ(Clamp(v->x_pos, 0, Map::MaxX() * TILE_SIZE), Clamp(v->y_pos, 0, Map::MaxY() * TILE_SIZE));
|
||||
v->z_pos -= 1;
|
||||
if (v->z_pos <= z) {
|
||||
|
@ -1189,18 +1179,12 @@ static bool HandleCrashedAircraft(Aircraft *v)
|
|||
if (v->crashed_counter < 650) {
|
||||
uint32_t r;
|
||||
if (Chance16R(1, 32, r)) {
|
||||
static const DirDiff delta[] = {
|
||||
DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
|
||||
};
|
||||
static const DirDiff delta[] = {DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT};
|
||||
|
||||
v->direction = ChangeDir(v->direction, delta[GB(r, 16, 2)]);
|
||||
SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
|
||||
r = Random();
|
||||
CreateEffectVehicleRel(v,
|
||||
GB(r, 0, 4) - 4,
|
||||
GB(r, 4, 4) - 4,
|
||||
GB(r, 8, 4),
|
||||
EV_EXPLOSION_SMALL);
|
||||
CreateEffectVehicleRel(v, GB(r, 0, 4) - 4, GB(r, 4, 4) - 4, GB(r, 8, 4), EV_EXPLOSION_SMALL);
|
||||
}
|
||||
} else if (v->crashed_counter >= 10000) {
|
||||
/* remove rubble of crashed airplane */
|
||||
|
@ -1211,7 +1195,7 @@ static bool HandleCrashedAircraft(Aircraft *v)
|
|||
if (st != nullptr) {
|
||||
st->airport.blocks.Reset(AirportBlock::RunwayIn);
|
||||
st->airport.blocks.Reset(AirportBlock::RunwayInOut); // commuter airport
|
||||
st->airport.blocks.Reset(AirportBlock::RunwayIn2); // intercontinental
|
||||
st->airport.blocks.Reset(AirportBlock::RunwayIn2); // intercontinental
|
||||
}
|
||||
|
||||
delete v;
|
||||
|
@ -1222,7 +1206,6 @@ static bool HandleCrashedAircraft(Aircraft *v)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle smoke of broken aircraft.
|
||||
* @param v Aircraft
|
||||
|
@ -1233,16 +1216,7 @@ static void HandleAircraftSmoke(Aircraft *v, bool mode)
|
|||
static const struct {
|
||||
int8_t x;
|
||||
int8_t y;
|
||||
} smoke_pos[] = {
|
||||
{ 5, 5 },
|
||||
{ 6, 0 },
|
||||
{ 5, -5 },
|
||||
{ 0, -6 },
|
||||
{ -5, -5 },
|
||||
{ -6, 0 },
|
||||
{ -5, 5 },
|
||||
{ 0, 6 }
|
||||
};
|
||||
} smoke_pos[] = {{5, 5}, {6, 0}, {5, -5}, {0, -6}, {-5, -5}, {-6, 0}, {-5, 5}, {0, 6}};
|
||||
|
||||
if (!v->vehstatus.Test(VehState::AircraftBroken)) return;
|
||||
|
||||
|
@ -1255,12 +1229,7 @@ static void HandleAircraftSmoke(Aircraft *v, bool mode)
|
|||
|
||||
/* Spawn effect et most once per Tick, i.e. !mode */
|
||||
if (!mode && (v->tick_counter & 0x0F) == 0) {
|
||||
CreateEffectVehicleRel(v,
|
||||
smoke_pos[v->direction].x,
|
||||
smoke_pos[v->direction].y,
|
||||
2,
|
||||
EV_BREAKDOWN_SMOKE_AIRCRAFT
|
||||
);
|
||||
CreateEffectVehicleRel(v, smoke_pos[v->direction].x, smoke_pos[v->direction].y, 2, EV_BREAKDOWN_SMOKE_AIRCRAFT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1293,7 +1262,6 @@ void HandleMissingAircraftOrders(Aircraft *v)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
TileIndex Aircraft::GetOrderStationLocation(StationID)
|
||||
{
|
||||
/* Orders are changed in flight, ensure going to the right station. */
|
||||
|
@ -1314,7 +1282,6 @@ void Aircraft::MarkDirty()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
uint Aircraft::Crash(bool flooded)
|
||||
{
|
||||
uint victims = Vehicle::Crash(flooded) + 2; // pilots
|
||||
|
@ -1345,8 +1312,10 @@ static void CrashAirplane(Aircraft *v)
|
|||
headline = GetEncodedString(STR_NEWS_AIRCRAFT_CRASH, victims, st->index);
|
||||
}
|
||||
|
||||
AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, vt, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING, victims, v->owner));
|
||||
Game::NewEvent(new ScriptEventVehicleCrashed(v->index, vt, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING, victims, v->owner));
|
||||
AI::NewEvent(v->owner,
|
||||
new ScriptEventVehicleCrashed(v->index, vt, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING, victims, v->owner));
|
||||
Game::NewEvent(
|
||||
new ScriptEventVehicleCrashed(v->index, vt, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING, victims, v->owner));
|
||||
|
||||
NewsType newstype = NewsType::Accident;
|
||||
if (v->owner != _local_company) {
|
||||
|
@ -1365,13 +1334,10 @@ static void CrashAirplane(Aircraft *v)
|
|||
*/
|
||||
static void MaybeCrashAirplane(Aircraft *v)
|
||||
{
|
||||
|
||||
Station *st = Station::Get(v->targetairport);
|
||||
|
||||
uint32_t prob;
|
||||
if (st->airport.GetFTA()->flags.Test(AirportFTAClass::Flag::ShortStrip) &&
|
||||
(AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) &&
|
||||
!_cheats.no_jetcrash.value) {
|
||||
if (st->airport.GetFTA()->flags.Test(AirportFTAClass::Flag::ShortStrip) && (AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) && !_cheats.no_jetcrash.value) {
|
||||
prob = 3276;
|
||||
} else {
|
||||
if (_settings_game.vehicle.plane_crashes == 0) return;
|
||||
|
@ -1405,12 +1371,7 @@ static void AircraftEntersTerminal(Aircraft *v)
|
|||
if (!(st->had_vehicle_of_type & HVOT_AIRCRAFT)) {
|
||||
st->had_vehicle_of_type |= HVOT_AIRCRAFT;
|
||||
/* show newsitem of celebrating citizens */
|
||||
AddVehicleNewsItem(
|
||||
GetEncodedString(STR_NEWS_FIRST_AIRCRAFT_ARRIVAL, st->index),
|
||||
(v->owner == _local_company) ? NewsType::ArrivalCompany : NewsType::ArrivalOther,
|
||||
v->index,
|
||||
st->index
|
||||
);
|
||||
AddVehicleNewsItem(GetEncodedString(STR_NEWS_FIRST_AIRCRAFT_ARRIVAL, st->index), (v->owner == _local_company) ? NewsType::ArrivalCompany : NewsType::ArrivalOther, v->index, st->index);
|
||||
AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
|
||||
Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
|
||||
}
|
||||
|
@ -1437,7 +1398,6 @@ static void AircraftLandAirplane(Aircraft *v)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/** set the right pos when heading to other airports after takeoff */
|
||||
void AircraftNextAirportPos_and_Order(Aircraft *v)
|
||||
{
|
||||
|
@ -1527,9 +1487,7 @@ static void AircraftEventHandler_InHangar(Aircraft *v, const AirportFTAClass *ap
|
|||
/* Check if we should wait here for unbunching. */
|
||||
if (v->IsWaitingForUnbunching()) return;
|
||||
|
||||
if (!v->current_order.IsType(OT_GOTO_STATION) &&
|
||||
!v->current_order.IsType(OT_GOTO_DEPOT))
|
||||
return;
|
||||
if (!v->current_order.IsType(OT_GOTO_STATION) && !v->current_order.IsType(OT_GOTO_DEPOT)) return;
|
||||
|
||||
/* We are leaving a hangar, but have to go to the exact same one; re-enter */
|
||||
if (v->current_order.IsType(OT_GOTO_DEPOT) && v->current_order.GetDestination() == v->targetairport) {
|
||||
|
@ -1591,7 +1549,7 @@ static void AircraftEventHandler_AtTerminal(Aircraft *v, const AirportFTAClass *
|
|||
switch (v->current_order.GetType()) {
|
||||
case OT_GOTO_STATION: // ready to fly to another airport
|
||||
break;
|
||||
case OT_GOTO_DEPOT: // visit hangar for servicing, sale, etc.
|
||||
case OT_GOTO_DEPOT: // visit hangar for servicing, sale, etc.
|
||||
go_to_hangar = v->current_order.GetDestination() == v->targetairport;
|
||||
break;
|
||||
case OT_CONDITIONAL:
|
||||
|
@ -1599,7 +1557,7 @@ static void AircraftEventHandler_AtTerminal(Aircraft *v, const AirportFTAClass *
|
|||
* longer, so the conditional order can actually be processed;
|
||||
* we should not clear the order as that makes us go nowhere. */
|
||||
return;
|
||||
default: // orders have been deleted (no orders), goto depot and don't bother us
|
||||
default: // orders have been deleted (no orders), goto depot and don't bother us
|
||||
v->current_order.Free();
|
||||
go_to_hangar = true;
|
||||
}
|
||||
|
@ -1694,7 +1652,7 @@ static void AircraftEventHandler_Flying(Aircraft *v, const AirportFTAClass *apc)
|
|||
static void AircraftEventHandler_Landing(Aircraft *v, const AirportFTAClass *)
|
||||
{
|
||||
v->state = ENDLANDING;
|
||||
AircraftLandAirplane(v); // maybe crash airplane
|
||||
AircraftLandAirplane(v); // maybe crash airplane
|
||||
|
||||
/* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */
|
||||
if (v->NeedsAutomaticServicing()) {
|
||||
|
@ -1723,7 +1681,6 @@ static void AircraftEventHandler_EndLanding(Aircraft *v, const AirportFTAClass *
|
|||
if (AirportFindFreeTerminal(v, apc)) return;
|
||||
}
|
||||
v->state = HANGAR;
|
||||
|
||||
}
|
||||
|
||||
static void AircraftEventHandler_HeliEndLanding(Aircraft *v, const AirportFTAClass *apc)
|
||||
|
@ -1751,29 +1708,29 @@ static void AircraftEventHandler_HeliEndLanding(Aircraft *v, const AirportFTACla
|
|||
*/
|
||||
typedef void AircraftStateHandler(Aircraft *v, const AirportFTAClass *apc);
|
||||
/** Array of handler functions for each target of the aircraft. */
|
||||
static AircraftStateHandler * const _aircraft_state_handlers[] = {
|
||||
AircraftEventHandler_General, // TO_ALL = 0
|
||||
AircraftEventHandler_InHangar, // HANGAR = 1
|
||||
AircraftEventHandler_AtTerminal, // TERM1 = 2
|
||||
AircraftEventHandler_AtTerminal, // TERM2 = 3
|
||||
AircraftEventHandler_AtTerminal, // TERM3 = 4
|
||||
AircraftEventHandler_AtTerminal, // TERM4 = 5
|
||||
AircraftEventHandler_AtTerminal, // TERM5 = 6
|
||||
AircraftEventHandler_AtTerminal, // TERM6 = 7
|
||||
AircraftEventHandler_AtTerminal, // HELIPAD1 = 8
|
||||
AircraftEventHandler_AtTerminal, // HELIPAD2 = 9
|
||||
AircraftEventHandler_TakeOff, // TAKEOFF = 10
|
||||
AircraftEventHandler_StartTakeOff, // STARTTAKEOFF = 11
|
||||
AircraftEventHandler_EndTakeOff, // ENDTAKEOFF = 12
|
||||
AircraftEventHandler_HeliTakeOff, // HELITAKEOFF = 13
|
||||
AircraftEventHandler_Flying, // FLYING = 14
|
||||
AircraftEventHandler_Landing, // LANDING = 15
|
||||
AircraftEventHandler_EndLanding, // ENDLANDING = 16
|
||||
AircraftEventHandler_HeliLanding, // HELILANDING = 17
|
||||
static AircraftStateHandler *const _aircraft_state_handlers[] = {
|
||||
AircraftEventHandler_General, // TO_ALL = 0
|
||||
AircraftEventHandler_InHangar, // HANGAR = 1
|
||||
AircraftEventHandler_AtTerminal, // TERM1 = 2
|
||||
AircraftEventHandler_AtTerminal, // TERM2 = 3
|
||||
AircraftEventHandler_AtTerminal, // TERM3 = 4
|
||||
AircraftEventHandler_AtTerminal, // TERM4 = 5
|
||||
AircraftEventHandler_AtTerminal, // TERM5 = 6
|
||||
AircraftEventHandler_AtTerminal, // TERM6 = 7
|
||||
AircraftEventHandler_AtTerminal, // HELIPAD1 = 8
|
||||
AircraftEventHandler_AtTerminal, // HELIPAD2 = 9
|
||||
AircraftEventHandler_TakeOff, // TAKEOFF = 10
|
||||
AircraftEventHandler_StartTakeOff, // STARTTAKEOFF = 11
|
||||
AircraftEventHandler_EndTakeOff, // ENDTAKEOFF = 12
|
||||
AircraftEventHandler_HeliTakeOff, // HELITAKEOFF = 13
|
||||
AircraftEventHandler_Flying, // FLYING = 14
|
||||
AircraftEventHandler_Landing, // LANDING = 15
|
||||
AircraftEventHandler_EndLanding, // ENDLANDING = 16
|
||||
AircraftEventHandler_HeliLanding, // HELILANDING = 17
|
||||
AircraftEventHandler_HeliEndLanding, // HELIENDLANDING = 18
|
||||
AircraftEventHandler_AtTerminal, // TERM7 = 19
|
||||
AircraftEventHandler_AtTerminal, // TERM8 = 20
|
||||
AircraftEventHandler_AtTerminal, // HELIPAD3 = 21
|
||||
AircraftEventHandler_AtTerminal, // TERM7 = 19
|
||||
AircraftEventHandler_AtTerminal, // TERM8 = 20
|
||||
AircraftEventHandler_AtTerminal, // HELIPAD3 = 21
|
||||
};
|
||||
|
||||
static void AirportClearBlock(const Aircraft *v, const AirportFTAClass *apc)
|
||||
|
@ -1802,7 +1759,7 @@ static bool AirportMove(Aircraft *v, const AirportFTAClass *apc)
|
|||
{
|
||||
/* error handling */
|
||||
if (v->pos >= apc->nofelements) {
|
||||
Debug(misc, 0, "[Ap] position {} is not valid for current airport. Max position is {}", v->pos, apc->nofelements-1);
|
||||
Debug(misc, 0, "[Ap] position {} is not valid for current airport. Max position is {}", v->pos, apc->nofelements - 1);
|
||||
assert(v->pos < apc->nofelements);
|
||||
}
|
||||
|
||||
|
@ -2130,7 +2087,6 @@ bool Aircraft::Tick()
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns aircraft's target station if v->target_airport
|
||||
* is a valid station with airport.
|
||||
|
@ -2164,8 +2120,7 @@ void UpdateAirplanesOnNewStation(const Station *st)
|
|||
Order *o = &v->current_order;
|
||||
/* The aircraft is heading to a hangar, but the new station doesn't have one,
|
||||
* or the aircraft can't land on the new station. Cancel current order. */
|
||||
if (o->IsType(OT_GOTO_DEPOT) && !(o->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) && o->GetDestination() == st->index &&
|
||||
(!st->airport.HasHangar() || !CanVehicleUseStation(v, st))) {
|
||||
if (o->IsType(OT_GOTO_DEPOT) && !(o->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) && o->GetDestination() == st->index && (!st->airport.HasHangar() || !CanVehicleUseStation(v, st))) {
|
||||
o->MakeDummy();
|
||||
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
|
||||
}
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
/** @file aircraft_gui.cpp The GUI of aircraft. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "aircraft.h"
|
||||
#include "vehicle_gui.h"
|
||||
#include "newgrf_engine.h"
|
||||
#include "spritecache.h"
|
||||
#include "strings_func.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "vehicle_gui.h"
|
||||
#include "window_gui.h"
|
||||
#include "spritecache.h"
|
||||
#include "zoom_func.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
@ -61,7 +62,6 @@ void DrawAircraftDetails(const Aircraft *v, const Rect &r)
|
|||
DrawString(r.left, r.right, y, GetString(STR_VEHICLE_INFO_FEEDER_CARGO_VALUE, feeder_share));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draws an image of an aircraft
|
||||
* @param v Front vehicle
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
/** @file airport.cpp Functions related to airports. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "station_base.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/airport_movement.h"
|
||||
#include "table/airporttile_ids.h"
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
||||
/**
|
||||
* Define a generic airport.
|
||||
* @param name Suffix of the names of the airport data.
|
||||
|
@ -65,11 +65,9 @@ AIRPORT_GENERIC(dummy, nullptr, 0, AirportFTAClass::Flags({AirportFTAClass::Flag
|
|||
|
||||
#include "table/airport_defaults.h"
|
||||
|
||||
|
||||
static uint16_t AirportGetNofElements(const AirportFTAbuildup *apFA);
|
||||
static void AirportBuildAutomata(std::vector<AirportFTA> &layout, uint8_t nofelements, const AirportFTAbuildup *apFA);
|
||||
|
||||
|
||||
/**
|
||||
* Rotate the airport moving data to another rotation.
|
||||
* @param orig Pointer to the moving data to rotate.
|
||||
|
@ -104,27 +102,15 @@ AirportMovingData RotateAirportMovingData(const AirportMovingData *orig, Directi
|
|||
amd.y = orig->x;
|
||||
break;
|
||||
|
||||
default: NOT_REACHED();
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
return amd;
|
||||
}
|
||||
|
||||
AirportFTAClass::AirportFTAClass(
|
||||
const AirportMovingData *moving_data_,
|
||||
const uint8_t *terminals_,
|
||||
const uint8_t num_helipads_,
|
||||
const uint8_t *entry_points_,
|
||||
Flags flags_,
|
||||
const AirportFTAbuildup *apFA,
|
||||
uint8_t delta_z_
|
||||
) :
|
||||
moving_data(moving_data_),
|
||||
terminals(terminals_),
|
||||
num_helipads(num_helipads_),
|
||||
flags(flags_),
|
||||
nofelements(AirportGetNofElements(apFA)),
|
||||
entry_points(entry_points_),
|
||||
delta_z(delta_z_)
|
||||
const AirportMovingData *moving_data_, const uint8_t *terminals_, const uint8_t num_helipads_, const uint8_t *entry_points_, Flags flags_, const AirportFTAbuildup *apFA, uint8_t delta_z_) :
|
||||
moving_data(moving_data_), terminals(terminals_), num_helipads(num_helipads_), flags(flags_), nofelements(AirportGetNofElements(apFA)), entry_points(entry_points_), delta_z(delta_z_)
|
||||
{
|
||||
/* Build the state machine itself */
|
||||
AirportBuildAutomata(this->layout, this->nofelements, apFA);
|
||||
|
@ -150,9 +136,7 @@ static uint16_t AirportGetNofElements(const AirportFTAbuildup *apFA)
|
|||
return nofelements;
|
||||
}
|
||||
|
||||
AirportFTA::AirportFTA(const AirportFTAbuildup &buildup) : blocks(buildup.blocks), position(buildup.position), next_position(buildup.next), heading(buildup.heading)
|
||||
{
|
||||
}
|
||||
AirportFTA::AirportFTA(const AirportFTAbuildup &buildup) : blocks(buildup.blocks), position(buildup.position), next_position(buildup.next), heading(buildup.heading) {}
|
||||
|
||||
/**
|
||||
* Construct the FTA given a description.
|
||||
|
|
190
src/airport.h
190
src/airport.h
|
@ -14,33 +14,33 @@
|
|||
#include "tile_type.h"
|
||||
|
||||
/** Some airport-related constants */
|
||||
static const uint MAX_TERMINALS = 8; ///< maximum number of terminals per airport
|
||||
static const uint MAX_HELIPADS = 3; ///< maximum number of helipads per airport
|
||||
static const uint MAX_ELEMENTS = 255; ///< maximum number of aircraft positions at airport
|
||||
static const uint MAX_TERMINALS = 8; ///< maximum number of terminals per airport
|
||||
static const uint MAX_HELIPADS = 3; ///< maximum number of helipads per airport
|
||||
static const uint MAX_ELEMENTS = 255; ///< maximum number of aircraft positions at airport
|
||||
|
||||
static const uint NUM_AIRPORTTILES_PER_GRF = 255; ///< Number of airport tiles per NewGRF; limited to 255 to allow extending Action3 with an extended byte later on.
|
||||
static const uint NUM_AIRPORTTILES_PER_GRF = 255; ///< Number of airport tiles per NewGRF; limited to 255 to allow extending Action3 with an extended byte later on.
|
||||
|
||||
static const uint NUM_AIRPORTTILES = 256; ///< Total number of airport tiles.
|
||||
static const uint NEW_AIRPORTTILE_OFFSET = 74; ///< offset of first newgrf airport tile
|
||||
static const uint INVALID_AIRPORTTILE = NUM_AIRPORTTILES; ///< id for an invalid airport tile
|
||||
static const uint NUM_AIRPORTTILES = 256; ///< Total number of airport tiles.
|
||||
static const uint NEW_AIRPORTTILE_OFFSET = 74; ///< offset of first newgrf airport tile
|
||||
static const uint INVALID_AIRPORTTILE = NUM_AIRPORTTILES; ///< id for an invalid airport tile
|
||||
|
||||
/** Airport types */
|
||||
enum AirportTypes : uint8_t {
|
||||
AT_SMALL = 0, ///< Small airport.
|
||||
AT_LARGE = 1, ///< Large airport.
|
||||
AT_HELIPORT = 2, ///< Heli port.
|
||||
AT_METROPOLITAN = 3, ///< Metropolitan airport.
|
||||
AT_INTERNATIONAL = 4, ///< International airport.
|
||||
AT_COMMUTER = 5, ///< Commuter airport.
|
||||
AT_HELIDEPOT = 6, ///< Heli depot.
|
||||
AT_INTERCON = 7, ///< Intercontinental airport.
|
||||
AT_HELISTATION = 8, ///< Heli station airport.
|
||||
AT_OILRIG = 9, ///< Oilrig airport.
|
||||
NEW_AIRPORT_OFFSET = 10, ///< Number of the first newgrf airport.
|
||||
AT_SMALL = 0, ///< Small airport.
|
||||
AT_LARGE = 1, ///< Large airport.
|
||||
AT_HELIPORT = 2, ///< Heli port.
|
||||
AT_METROPOLITAN = 3, ///< Metropolitan airport.
|
||||
AT_INTERNATIONAL = 4, ///< International airport.
|
||||
AT_COMMUTER = 5, ///< Commuter airport.
|
||||
AT_HELIDEPOT = 6, ///< Heli depot.
|
||||
AT_INTERCON = 7, ///< Intercontinental airport.
|
||||
AT_HELISTATION = 8, ///< Heli station airport.
|
||||
AT_OILRIG = 9, ///< Oilrig airport.
|
||||
NEW_AIRPORT_OFFSET = 10, ///< Number of the first newgrf airport.
|
||||
NUM_AIRPORTS_PER_GRF = 128, ///< Maximal number of airports per NewGRF.
|
||||
NUM_AIRPORTS = 128, ///< Maximal number of airports in total.
|
||||
AT_INVALID = 254, ///< Invalid airport.
|
||||
AT_DUMMY = 255, ///< Dummy airport.
|
||||
NUM_AIRPORTS = 128, ///< Maximal number of airports in total.
|
||||
AT_INVALID = 254, ///< Invalid airport.
|
||||
AT_DUMMY = 255, ///< Dummy airport.
|
||||
};
|
||||
|
||||
/** Flags for airport movement data. */
|
||||
|
@ -60,81 +60,81 @@ using AirportMovingDataFlags = EnumBitSet<AirportMovingDataFlag, uint16_t>;
|
|||
|
||||
/** Movement States on Airports (headings target) */
|
||||
enum AirportMovementStates : uint8_t {
|
||||
TO_ALL = 0, ///< Go in this direction for every target.
|
||||
HANGAR = 1, ///< Heading for hangar.
|
||||
TERM1 = 2, ///< Heading for terminal 1.
|
||||
TERM2 = 3, ///< Heading for terminal 2.
|
||||
TERM3 = 4, ///< Heading for terminal 3.
|
||||
TERM4 = 5, ///< Heading for terminal 4.
|
||||
TERM5 = 6, ///< Heading for terminal 5.
|
||||
TERM6 = 7, ///< Heading for terminal 6.
|
||||
HELIPAD1 = 8, ///< Heading for helipad 1.
|
||||
HELIPAD2 = 9, ///< Heading for helipad 2.
|
||||
TAKEOFF = 10, ///< Airplane wants to leave the airport.
|
||||
STARTTAKEOFF = 11, ///< Airplane has arrived at a runway for take-off.
|
||||
ENDTAKEOFF = 12, ///< Airplane has reached end-point of the take-off runway.
|
||||
HELITAKEOFF = 13, ///< Helicopter wants to leave the airport.
|
||||
FLYING = 14, ///< %Vehicle is flying in the air.
|
||||
LANDING = 15, ///< Airplane wants to land.
|
||||
ENDLANDING = 16, ///< Airplane wants to finish landing.
|
||||
HELILANDING = 17, ///< Helicopter wants to land.
|
||||
HELIENDLANDING = 18, ///< Helicopter wants to finish landing.
|
||||
TERM7 = 19, ///< Heading for terminal 7.
|
||||
TERM8 = 20, ///< Heading for terminal 8.
|
||||
HELIPAD3 = 21, ///< Heading for helipad 3.
|
||||
MAX_HEADINGS = 21, ///< Last valid target to head for.
|
||||
TERMGROUP = 255, ///< Aircraft is looking for a free terminal in a terminalgroup.
|
||||
TO_ALL = 0, ///< Go in this direction for every target.
|
||||
HANGAR = 1, ///< Heading for hangar.
|
||||
TERM1 = 2, ///< Heading for terminal 1.
|
||||
TERM2 = 3, ///< Heading for terminal 2.
|
||||
TERM3 = 4, ///< Heading for terminal 3.
|
||||
TERM4 = 5, ///< Heading for terminal 4.
|
||||
TERM5 = 6, ///< Heading for terminal 5.
|
||||
TERM6 = 7, ///< Heading for terminal 6.
|
||||
HELIPAD1 = 8, ///< Heading for helipad 1.
|
||||
HELIPAD2 = 9, ///< Heading for helipad 2.
|
||||
TAKEOFF = 10, ///< Airplane wants to leave the airport.
|
||||
STARTTAKEOFF = 11, ///< Airplane has arrived at a runway for take-off.
|
||||
ENDTAKEOFF = 12, ///< Airplane has reached end-point of the take-off runway.
|
||||
HELITAKEOFF = 13, ///< Helicopter wants to leave the airport.
|
||||
FLYING = 14, ///< %Vehicle is flying in the air.
|
||||
LANDING = 15, ///< Airplane wants to land.
|
||||
ENDLANDING = 16, ///< Airplane wants to finish landing.
|
||||
HELILANDING = 17, ///< Helicopter wants to land.
|
||||
HELIENDLANDING = 18, ///< Helicopter wants to finish landing.
|
||||
TERM7 = 19, ///< Heading for terminal 7.
|
||||
TERM8 = 20, ///< Heading for terminal 8.
|
||||
HELIPAD3 = 21, ///< Heading for helipad 3.
|
||||
MAX_HEADINGS = 21, ///< Last valid target to head for.
|
||||
TERMGROUP = 255, ///< Aircraft is looking for a free terminal in a terminalgroup.
|
||||
};
|
||||
|
||||
/** Movement Blocks on Airports blocks (eg_airport_flags). */
|
||||
enum class AirportBlock : uint8_t {
|
||||
Term1 = 0, ///< Block belonging to terminal 1.
|
||||
Term2 = 1, ///< Block belonging to terminal 2.
|
||||
Term3 = 2, ///< Block belonging to terminal 3.
|
||||
Term4 = 3, ///< Block belonging to terminal 4.
|
||||
Term5 = 4, ///< Block belonging to terminal 5.
|
||||
Term6 = 5, ///< Block belonging to terminal 6.
|
||||
Helipad1 = 6, ///< Block belonging to helipad 1.
|
||||
Helipad2 = 7, ///< Block belonging to helipad 2.
|
||||
RunwayInOut = 8,
|
||||
RunwayIn = 8,
|
||||
AirportBusy = 8,
|
||||
RunwayOut = 9,
|
||||
TaxiwayBusy = 10,
|
||||
OutWay = 11,
|
||||
InWay = 12,
|
||||
AirportEntrance = 13,
|
||||
TermGroup1 = 14,
|
||||
TermGroup2 = 15,
|
||||
Hangar2Area = 16,
|
||||
Term1 = 0, ///< Block belonging to terminal 1.
|
||||
Term2 = 1, ///< Block belonging to terminal 2.
|
||||
Term3 = 2, ///< Block belonging to terminal 3.
|
||||
Term4 = 3, ///< Block belonging to terminal 4.
|
||||
Term5 = 4, ///< Block belonging to terminal 5.
|
||||
Term6 = 5, ///< Block belonging to terminal 6.
|
||||
Helipad1 = 6, ///< Block belonging to helipad 1.
|
||||
Helipad2 = 7, ///< Block belonging to helipad 2.
|
||||
RunwayInOut = 8,
|
||||
RunwayIn = 8,
|
||||
AirportBusy = 8,
|
||||
RunwayOut = 9,
|
||||
TaxiwayBusy = 10,
|
||||
OutWay = 11,
|
||||
InWay = 12,
|
||||
AirportEntrance = 13,
|
||||
TermGroup1 = 14,
|
||||
TermGroup2 = 15,
|
||||
Hangar2Area = 16,
|
||||
TermGroup2Enter1 = 17,
|
||||
TermGroup2Enter2 = 18,
|
||||
TermGroup2Exit1 = 19,
|
||||
TermGroup2Exit2 = 20,
|
||||
PreHelipad = 21,
|
||||
TermGroup2Exit1 = 19,
|
||||
TermGroup2Exit2 = 20,
|
||||
PreHelipad = 21,
|
||||
|
||||
/* blocks for new airports */
|
||||
Term7 = 22, ///< Block belonging to terminal 7.
|
||||
Term8 = 23, ///< Block belonging to terminal 8.
|
||||
Helipad3 = 24, ///< Block belonging to helipad 3.
|
||||
Hangar1Area = 26,
|
||||
OutWay2 = 27,
|
||||
InWay2 = 28,
|
||||
RunwayIn2 = 29,
|
||||
RunwayOut2 = 10, ///< @note re-uses #AirportBlock::TaxiwayBusy
|
||||
HelipadGroup = 13, ///< @note re-uses #AirportBlock::AirportEntrance
|
||||
OutWay3 = 31,
|
||||
Term7 = 22, ///< Block belonging to terminal 7.
|
||||
Term8 = 23, ///< Block belonging to terminal 8.
|
||||
Helipad3 = 24, ///< Block belonging to helipad 3.
|
||||
Hangar1Area = 26,
|
||||
OutWay2 = 27,
|
||||
InWay2 = 28,
|
||||
RunwayIn2 = 29,
|
||||
RunwayOut2 = 10, ///< @note re-uses #AirportBlock::TaxiwayBusy
|
||||
HelipadGroup = 13, ///< @note re-uses #AirportBlock::AirportEntrance
|
||||
OutWay3 = 31,
|
||||
/* end of new blocks */
|
||||
|
||||
Nothing = 30,
|
||||
AirportClosed = 63, ///< Dummy block for indicating a closed airport.
|
||||
Nothing = 30,
|
||||
AirportClosed = 63, ///< Dummy block for indicating a closed airport.
|
||||
};
|
||||
using AirportBlocks = EnumBitSet<AirportBlock, uint64_t>;
|
||||
|
||||
/** A single location on an airport where aircraft can move to. */
|
||||
struct AirportMovingData {
|
||||
int16_t x; ///< x-coordinate of the destination.
|
||||
int16_t y; ///< y-coordinate of the destination.
|
||||
int16_t x; ///< x-coordinate of the destination.
|
||||
int16_t y; ///< y-coordinate of the destination.
|
||||
AirportMovingDataFlags flags; ///< special flags when moving towards the destination.
|
||||
Direction direction; ///< Direction to turn the aircraft after reaching the destination.
|
||||
};
|
||||
|
@ -145,7 +145,7 @@ struct AirportFTAbuildup;
|
|||
|
||||
/** Internal structure used in openttd - Finite sTate mAchine --> FTA */
|
||||
struct AirportFTA {
|
||||
AirportFTA(const AirportFTAbuildup&);
|
||||
AirportFTA(const AirportFTAbuildup &);
|
||||
|
||||
std::unique_ptr<AirportFTA> next; ///< possible extra movement choices from this position
|
||||
AirportBlocks blocks; ///< bitmap of blocks that could be reserved
|
||||
|
@ -159,21 +159,14 @@ struct AirportFTAClass {
|
|||
public:
|
||||
/** Bitmask of airport flags. */
|
||||
enum class Flag : uint8_t {
|
||||
Airplanes = 0, ///< Can planes land on this airport type?
|
||||
Airplanes = 0, ///< Can planes land on this airport type?
|
||||
Helicopters = 1, ///< Can helicopters land on this airport type?
|
||||
ShortStrip = 2, ///< This airport has a short landing strip, dangerous for fast aircraft.
|
||||
ShortStrip = 2, ///< This airport has a short landing strip, dangerous for fast aircraft.
|
||||
};
|
||||
using Flags = EnumBitSet<Flag, uint8_t>;
|
||||
|
||||
AirportFTAClass(
|
||||
const AirportMovingData *moving_data,
|
||||
const uint8_t *terminals,
|
||||
const uint8_t num_helipads,
|
||||
const uint8_t *entry_points,
|
||||
Flags flags,
|
||||
const AirportFTAbuildup *apFA,
|
||||
uint8_t delta_z
|
||||
);
|
||||
const AirportMovingData *moving_data, const uint8_t *terminals, const uint8_t num_helipads, const uint8_t *entry_points, Flags flags, const AirportFTAbuildup *apFA, uint8_t delta_z);
|
||||
|
||||
/**
|
||||
* Get movement data at a position.
|
||||
|
@ -188,15 +181,14 @@ public:
|
|||
|
||||
const AirportMovingData *moving_data; ///< Movement data.
|
||||
std::vector<AirportFTA> layout; ///< state machine for airport
|
||||
const uint8_t *terminals; ///< %Array with the number of terminal groups, followed by the number of terminals in each group.
|
||||
const uint8_t num_helipads; ///< Number of helipads on this airport. When 0 helicopters will go to normal terminals.
|
||||
Flags flags; ///< Flags for this airport type.
|
||||
uint8_t nofelements; ///< number of positions the airport consists of
|
||||
const uint8_t *entry_points; ///< when an airplane arrives at this airport, enter it at position entry_point, index depends on direction
|
||||
uint8_t delta_z; ///< Z adjustment for helicopter pads
|
||||
const uint8_t *terminals; ///< %Array with the number of terminal groups, followed by the number of terminals in each group.
|
||||
const uint8_t num_helipads; ///< Number of helipads on this airport. When 0 helicopters will go to normal terminals.
|
||||
Flags flags; ///< Flags for this airport type.
|
||||
uint8_t nofelements; ///< number of positions the airport consists of
|
||||
const uint8_t *entry_points; ///< when an airplane arrives at this airport, enter it at position entry_point, index depends on direction
|
||||
uint8_t delta_z; ///< Z adjustment for helicopter pads
|
||||
};
|
||||
|
||||
|
||||
const AirportFTAClass *GetAirport(const uint8_t airport_type);
|
||||
uint8_t GetVehiclePosOnBuild(TileIndex hangar_tile);
|
||||
|
||||
|
|
|
@ -8,44 +8,43 @@
|
|||
/** @file airport_gui.cpp The GUI for airports. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "economy_func.h"
|
||||
#include "window_gui.h"
|
||||
#include "station_gui.h"
|
||||
#include "terraform_gui.h"
|
||||
#include "sound_func.h"
|
||||
#include "window_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "viewport_func.h"
|
||||
#include "company_func.h"
|
||||
#include "tilehighlight_func.h"
|
||||
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "airport_cmd.h"
|
||||
#include "command_func.h"
|
||||
#include "company_base.h"
|
||||
#include "station_type.h"
|
||||
#include "company_func.h"
|
||||
#include "dropdown_func.h"
|
||||
#include "dropdown_type.h"
|
||||
#include "economy_func.h"
|
||||
#include "gui.h"
|
||||
#include "hotkeys.h"
|
||||
#include "newgrf_airport.h"
|
||||
#include "newgrf_badge_gui.h"
|
||||
#include "newgrf_callbacks.h"
|
||||
#include "dropdown_type.h"
|
||||
#include "dropdown_func.h"
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "hotkeys.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "gui.h"
|
||||
#include "command_func.h"
|
||||
#include "airport_cmd.h"
|
||||
#include "sound_func.h"
|
||||
#include "station_cmd.h"
|
||||
#include "zoom_func.h"
|
||||
#include "station_gui.h"
|
||||
#include "station_type.h"
|
||||
#include "strings_func.h"
|
||||
#include "terraform_gui.h"
|
||||
#include "tilehighlight_func.h"
|
||||
#include "timer/timer.h"
|
||||
#include "timer/timer_game_calendar.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "viewport_func.h"
|
||||
#include "window_func.h"
|
||||
#include "window_gui.h"
|
||||
#include "zoom_func.h"
|
||||
|
||||
#include "widgets/airport_widget.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
||||
static AirportClassID _selected_airport_class; ///< the currently visible airport class
|
||||
static int _selected_airport_index; ///< the index of the selected airport in the current class or -1
|
||||
static uint8_t _selected_airport_layout; ///< selected airport layout number.
|
||||
static int _selected_airport_index; ///< the index of the selected airport in the current class or -1
|
||||
static uint8_t _selected_airport_layout; ///< selected airport layout number.
|
||||
|
||||
static void ShowBuildAirportPicker(Window *parent);
|
||||
|
||||
|
@ -136,11 +135,11 @@ struct BuildAirToolbarWindow : Window {
|
|||
this->last_user_action = widget;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
|
||||
{
|
||||
switch (this->last_user_action) {
|
||||
|
@ -152,7 +151,8 @@ struct BuildAirToolbarWindow : Window {
|
|||
PlaceProc_DemolishArea(tile);
|
||||
break;
|
||||
|
||||
default: NOT_REACHED();
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,10 +191,12 @@ struct BuildAirToolbarWindow : Window {
|
|||
return w->OnHotkey(hotkey);
|
||||
}
|
||||
|
||||
static inline HotkeyList hotkeys{"airtoolbar", {
|
||||
Hotkey('1', "airport", WID_AT_AIRPORT),
|
||||
Hotkey('2', "demolish", WID_AT_DEMOLISH),
|
||||
}, AirportToolbarGlobalHotkeys};
|
||||
static inline HotkeyList hotkeys{"airtoolbar",
|
||||
{
|
||||
Hotkey('1', "airport", WID_AT_AIRPORT),
|
||||
Hotkey('2', "demolish", WID_AT_DEMOLISH),
|
||||
},
|
||||
AirportToolbarGlobalHotkeys};
|
||||
};
|
||||
|
||||
/* clang-format off */
|
||||
|
@ -212,13 +214,7 @@ static constexpr NWidgetPart _nested_air_toolbar_widgets[] = {
|
|||
};
|
||||
/* clang-format on */
|
||||
|
||||
static WindowDesc _air_toolbar_desc(
|
||||
WDP_ALIGN_TOOLBAR, "toolbar_air", 0, 0,
|
||||
WC_BUILD_TOOLBAR, WC_NONE,
|
||||
WindowDefaultFlag::Construction,
|
||||
_nested_air_toolbar_widgets,
|
||||
&BuildAirToolbarWindow::hotkeys
|
||||
);
|
||||
static WindowDesc _air_toolbar_desc(WDP_ALIGN_TOOLBAR, "toolbar_air", 0, 0, WC_BUILD_TOOLBAR, WC_NONE, WindowDefaultFlag::Construction, _nested_air_toolbar_widgets, &BuildAirToolbarWindow::hotkeys);
|
||||
|
||||
/**
|
||||
* Open the build airport toolbar window
|
||||
|
@ -376,7 +372,8 @@ public:
|
|||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -506,7 +503,8 @@ public:
|
|||
break;
|
||||
}
|
||||
|
||||
case WID_AP_BTN_DONTHILIGHT: case WID_AP_BTN_DOHILIGHT:
|
||||
case WID_AP_BTN_DONTHILIGHT:
|
||||
case WID_AP_BTN_DOHILIGHT:
|
||||
_settings_client.gui.station_show_coverage = (widget != WID_AP_BTN_DONTHILIGHT);
|
||||
this->SetWidgetLoweredState(WID_AP_BTN_DONTHILIGHT, !_settings_client.gui.station_show_coverage);
|
||||
this->SetWidgetLoweredState(WID_AP_BTN_DOHILIGHT, _settings_client.gui.station_show_coverage);
|
||||
|
@ -578,8 +576,8 @@ public:
|
|||
}
|
||||
|
||||
IntervalTimer<TimerGameCalendar> yearly_interval = {{TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE}, [this](auto) {
|
||||
this->InvalidateData();
|
||||
}};
|
||||
this->InvalidateData();
|
||||
}};
|
||||
};
|
||||
|
||||
/* clang-format off */
|
||||
|
@ -621,12 +619,7 @@ static constexpr NWidgetPart _nested_build_airport_widgets[] = {
|
|||
};
|
||||
/* clang-format on */
|
||||
|
||||
static WindowDesc _build_airport_desc(
|
||||
WDP_AUTO, nullptr, 0, 0,
|
||||
WC_BUILD_STATION, WC_BUILD_TOOLBAR,
|
||||
WindowDefaultFlag::Construction,
|
||||
_nested_build_airport_widgets
|
||||
);
|
||||
static WindowDesc _build_airport_desc(WDP_AUTO, nullptr, 0, 0, WC_BUILD_STATION, WC_BUILD_TOOLBAR, WindowDefaultFlag::Construction, _nested_build_airport_widgets);
|
||||
|
||||
static void ShowBuildAirportPicker(Window *parent)
|
||||
{
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
/** @file animated_tile.cpp Everything related to animated tiles. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "animated_tile_func.h"
|
||||
#include "animated_tile_map.h"
|
||||
#include "framerate_type.h"
|
||||
#include "tile_cmd.h"
|
||||
#include "viewport_func.h"
|
||||
#include "framerate_type.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
|
|
@ -8,14 +8,15 @@
|
|||
/** @file articulated_vehicles.cpp Implementation of articulated vehicles. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "core/bitmath_func.hpp"
|
||||
#include "core/random_func.hpp"
|
||||
#include "train.h"
|
||||
#include "roadveh.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "engine_func.h"
|
||||
#include "company_func.h"
|
||||
#include "engine_func.h"
|
||||
#include "newgrf.h"
|
||||
#include "roadveh.h"
|
||||
#include "train.h"
|
||||
#include "vehicle_func.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
|
@ -97,7 +98,6 @@ uint CountArticulatedParts(EngineID engine_type, bool purchase_window)
|
|||
return i - 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the default (non-refitted) cargo and capacity of a specific EngineID.
|
||||
* @param engine the EngineID of interest
|
||||
|
@ -355,7 +355,8 @@ void AddArticulatedParts(Vehicle *first)
|
|||
|
||||
const Engine *e_artic = Engine::Get(engine_type);
|
||||
switch (type) {
|
||||
default: NOT_REACHED();
|
||||
default:
|
||||
NOT_REACHED();
|
||||
|
||||
case VEH_TRAIN: {
|
||||
Train *front = Train::From(first);
|
||||
|
@ -370,7 +371,7 @@ void AddArticulatedParts(Vehicle *first)
|
|||
t->spritenum = e_artic->u.rail.image_index;
|
||||
if (e_artic->CanCarryCargo()) {
|
||||
t->cargo_type = e_artic->GetDefaultCargoType();
|
||||
t->cargo_cap = e_artic->u.rail.capacity; // Callback 36 is called when the consist is finished
|
||||
t->cargo_cap = e_artic->u.rail.capacity; // Callback 36 is called when the consist is finished
|
||||
} else {
|
||||
t->cargo_type = front->cargo_type; // Needed for livery selection
|
||||
t->cargo_cap = 0;
|
||||
|
@ -398,7 +399,7 @@ void AddArticulatedParts(Vehicle *first)
|
|||
if (e_artic->CanCarryCargo()) {
|
||||
rv->cargo_type = e_artic->GetDefaultCargoType();
|
||||
assert(IsValidCargoType(rv->cargo_type));
|
||||
rv->cargo_cap = e_artic->u.road.capacity; // Callback 36 is called when the consist is finished
|
||||
rv->cargo_cap = e_artic->u.road.capacity; // Callback 36 is called when the consist is finished
|
||||
} else {
|
||||
rv->cargo_type = front->cargo_type; // Needed for livery selection
|
||||
rv->cargo_cap = 0;
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
#ifndef ARTICULATED_VEHICLES_H
|
||||
#define ARTICULATED_VEHICLES_H
|
||||
|
||||
#include "vehicle_type.h"
|
||||
#include "engine_type.h"
|
||||
#include "vehicle_type.h"
|
||||
|
||||
uint CountArticulatedParts(EngineID engine_type, bool purchase_window);
|
||||
CargoArray GetCapacityOfArticulatedParts(EngineID engine);
|
||||
|
@ -24,5 +24,4 @@ bool IsArticulatedVehicleRefittable(EngineID engine);
|
|||
bool IsArticulatedEngine(EngineID engine_type);
|
||||
void CheckConsistencyOfArticulatedVehicle(const Vehicle *v);
|
||||
|
||||
|
||||
#endif /* ARTICULATED_VEHICLES_H */
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
#include "autocompletion.h"
|
||||
|
||||
#include "console_internal.h"
|
||||
#include "town.h"
|
||||
#include "network/network_base.h"
|
||||
#include "town.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
|
|
@ -17,19 +17,20 @@ protected:
|
|||
Textbuf *textbuf;
|
||||
|
||||
private:
|
||||
std::string initial_buf; ///< Value of text buffer when we started current suggestion session.
|
||||
std::string initial_buf; ///< Value of text buffer when we started current suggestion session.
|
||||
|
||||
std::string_view prefix; ///< Prefix of the text before the last space.
|
||||
std::string_view query; ///< Last token of the text. This is used to based the suggestions on.
|
||||
std::string_view prefix; ///< Prefix of the text before the last space.
|
||||
std::string_view query; ///< Last token of the text. This is used to based the suggestions on.
|
||||
|
||||
std::vector<std::string> suggestions;
|
||||
size_t current_suggestion_index;
|
||||
size_t current_suggestion_index;
|
||||
|
||||
public:
|
||||
AutoCompletion(Textbuf *textbuf) : textbuf(textbuf)
|
||||
{
|
||||
this->Reset();
|
||||
}
|
||||
|
||||
virtual ~AutoCompletion() = default;
|
||||
|
||||
bool AutoComplete();
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
/** @file autoreplace.cpp Management of replacement lists. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "command_func.h"
|
||||
#include "group.h"
|
||||
#include "autoreplace_base.h"
|
||||
|
||||
#include "core/bitmath_func.hpp"
|
||||
#include "core/pool_func.hpp"
|
||||
#include "autoreplace_base.h"
|
||||
#include "command_func.h"
|
||||
#include "group.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
|
|
@ -38,8 +38,9 @@ struct EngineRenew : EngineRenewPool::PoolItem<&_enginerenew_pool> {
|
|||
bool replace_when_old = false; ///< Do replacement only when vehicle is old.
|
||||
|
||||
EngineRenew() {}
|
||||
EngineRenew(EngineID from, EngineID to, GroupID group_id, bool replace_when_old, EngineRenew *next) :
|
||||
from(from), to(to), next(next), group_id(group_id), replace_when_old(replace_when_old) {}
|
||||
|
||||
EngineRenew(EngineID from, EngineID to, GroupID group_id, bool replace_when_old, EngineRenew *next) : from(from), to(to), next(next), group_id(group_id), replace_when_old(replace_when_old) {}
|
||||
|
||||
~EngineRenew() {}
|
||||
};
|
||||
|
||||
|
|
|
@ -8,26 +8,28 @@
|
|||
/** @file autoreplace_cmd.cpp Deals with autoreplace execution but not the setup */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "company_func.h"
|
||||
#include "train.h"
|
||||
#include "command_func.h"
|
||||
#include "engine_func.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "autoreplace_func.h"
|
||||
#include "autoreplace_gui.h"
|
||||
#include "articulated_vehicles.h"
|
||||
|
||||
#include "autoreplace_cmd.h"
|
||||
|
||||
#include "core/bitmath_func.hpp"
|
||||
#include "core/random_func.hpp"
|
||||
#include "vehiclelist.h"
|
||||
#include "road.h"
|
||||
#include "ai/ai.hpp"
|
||||
#include "news_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "autoreplace_cmd.h"
|
||||
#include "articulated_vehicles.h"
|
||||
#include "autoreplace_func.h"
|
||||
#include "autoreplace_gui.h"
|
||||
#include "command_func.h"
|
||||
#include "company_func.h"
|
||||
#include "engine_func.h"
|
||||
#include "group_cmd.h"
|
||||
#include "news_func.h"
|
||||
#include "order_cmd.h"
|
||||
#include "road.h"
|
||||
#include "strings_func.h"
|
||||
#include "train.h"
|
||||
#include "train_cmd.h"
|
||||
#include "vehicle_cmd.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "vehiclelist.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
|
@ -91,7 +93,8 @@ bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company)
|
|||
if ((e_from->u.air.subtype & AIR_CTOL) != (e_to->u.air.subtype & AIR_CTOL)) return false;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* the engines needs to be able to carry the same cargo */
|
||||
|
@ -340,16 +343,11 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic
|
|||
int order_id = GetIncompatibleRefitOrderIdForAutoreplace(old_veh, e);
|
||||
if (order_id != -1) {
|
||||
/* Orders contained a refit order that is incompatible with the new vehicle. */
|
||||
headline = GetEncodedString(STR_NEWS_VEHICLE_AUTORENEW_FAILED,
|
||||
old_veh_id,
|
||||
STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT,
|
||||
headline = GetEncodedString(STR_NEWS_VEHICLE_AUTORENEW_FAILED, old_veh_id, STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT,
|
||||
order_id + 1); // 1-based indexing for display
|
||||
} else {
|
||||
/* Current cargo is incompatible with the new vehicle. */
|
||||
headline = GetEncodedString(STR_NEWS_VEHICLE_AUTORENEW_FAILED,
|
||||
old_veh_id,
|
||||
STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO,
|
||||
CargoSpec::Get(old_veh->cargo_type)->name);
|
||||
headline = GetEncodedString(STR_NEWS_VEHICLE_AUTORENEW_FAILED, old_veh_id, STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO, CargoSpec::Get(old_veh->cargo_type)->name);
|
||||
}
|
||||
|
||||
AddVehicleAdviceNewsItem(AdviceType::AutorenewFailed, std::move(headline), old_veh_id);
|
||||
|
@ -358,7 +356,8 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic
|
|||
|
||||
/* Build the new vehicle */
|
||||
VehicleID new_veh_id;
|
||||
std::tie(cost, new_veh_id, std::ignore, std::ignore, std::ignore) = Command<CMD_BUILD_VEHICLE>::Do({DoCommandFlag::Execute, DoCommandFlag::AutoReplace}, old_veh->tile, e, true, INVALID_CARGO, INVALID_CLIENT_ID);
|
||||
std::tie(cost, new_veh_id, std::ignore, std::ignore, std::ignore) =
|
||||
Command<CMD_BUILD_VEHICLE>::Do({DoCommandFlag::Execute, DoCommandFlag::AutoReplace}, old_veh->tile, e, true, INVALID_CARGO, INVALID_CLIENT_ID);
|
||||
if (cost.Failed()) return cost;
|
||||
|
||||
Vehicle *new_veh = Vehicle::Get(new_veh_id);
|
||||
|
@ -418,7 +417,8 @@ static CommandCost CopyHeadSpecificThings(Vehicle *old_head, Vehicle *new_head,
|
|||
if (cost.Succeeded() && old_head != new_head) cost.AddCost(Command<CMD_CLONE_ORDER>::Do(DoCommandFlag::Execute, CO_SHARE, new_head->index, old_head->index));
|
||||
|
||||
/* Copy group membership */
|
||||
if (cost.Succeeded() && old_head != new_head) cost.AddCost(std::get<0>(Command<CMD_ADD_VEHICLE_GROUP>::Do(DoCommandFlag::Execute, old_head->group_id, new_head->index, false, VehicleListIdentifier{})));
|
||||
if (cost.Succeeded() && old_head != new_head)
|
||||
cost.AddCost(std::get<0>(Command<CMD_ADD_VEHICLE_GROUP>::Do(DoCommandFlag::Execute, old_head->group_id, new_head->index, false, VehicleListIdentifier{})));
|
||||
|
||||
/* Perform start/stop check whether the new vehicle suits newgrf restrictions etc. */
|
||||
if (cost.Succeeded()) {
|
||||
|
@ -502,13 +502,16 @@ struct ReplaceChainItem {
|
|||
Vehicle *new_veh; ///< Replacement vehicle, or nullptr if no replacement.
|
||||
Money cost; /// Cost of buying and refitting replacement.
|
||||
|
||||
ReplaceChainItem(Vehicle *old_veh, Vehicle *new_veh, Money cost) : old_veh(old_veh), new_veh(new_veh), cost(cost) { }
|
||||
ReplaceChainItem(Vehicle *old_veh, Vehicle *new_veh, Money cost) : old_veh(old_veh), new_veh(new_veh), cost(cost) {}
|
||||
|
||||
/**
|
||||
* Get vehicle to use for this position.
|
||||
* @return Either the new vehicle, or the old vehicle if there is no replacement.
|
||||
*/
|
||||
Vehicle *GetVehicle() const { return new_veh == nullptr ? old_veh : new_veh; }
|
||||
Vehicle *GetVehicle() const
|
||||
{
|
||||
return new_veh == nullptr ? old_veh : new_veh;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -852,4 +855,3 @@ CommandCost CmdSetAutoReplace(DoCommandFlags flags, GroupID id_g, EngineID old_e
|
|||
|
||||
return cost;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
#define AUTOREPLACE_CMD_H
|
||||
|
||||
#include "command_type.h"
|
||||
#include "vehicle_type.h"
|
||||
#include "engine_type.h"
|
||||
#include "group_type.h"
|
||||
#include "vehicle_type.h"
|
||||
|
||||
CommandCost CmdAutoreplaceVehicle(DoCommandFlags flags, VehicleID veh_id);
|
||||
CommandCost CmdSetAutoReplace(DoCommandFlags flags, GroupID id_g, EngineID old_engine_type, EngineID new_engine_type, bool when_old);
|
||||
|
||||
DEF_CMD_TRAIT(CMD_AUTOREPLACE_VEHICLE, CmdAutoreplaceVehicle, {}, CMDT_VEHICLE_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_SET_AUTOREPLACE, CmdSetAutoReplace, {}, CMDT_VEHICLE_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_SET_AUTOREPLACE, CmdSetAutoReplace, {}, CMDT_VEHICLE_MANAGEMENT)
|
||||
|
||||
#endif /* AUTOREPLACE_CMD_H */
|
||||
|
|
|
@ -8,31 +8,31 @@
|
|||
/** @file autoreplace_gui.cpp GUI for autoreplace handling. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "autoreplace_cmd.h"
|
||||
#include "autoreplace_func.h"
|
||||
#include "command_func.h"
|
||||
#include "vehicle_gui.h"
|
||||
#include "company_func.h"
|
||||
#include "dropdown_func.h"
|
||||
#include "dropdown_type.h"
|
||||
#include "engine_base.h"
|
||||
#include "engine_gui.h"
|
||||
#include "group_cmd.h"
|
||||
#include "newgrf_badge.h"
|
||||
#include "newgrf_engine.h"
|
||||
#include "rail.h"
|
||||
#include "road.h"
|
||||
#include "strings_func.h"
|
||||
#include "window_func.h"
|
||||
#include "autoreplace_func.h"
|
||||
#include "company_func.h"
|
||||
#include "engine_base.h"
|
||||
#include "window_gui.h"
|
||||
#include "engine_gui.h"
|
||||
#include "settings_func.h"
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "rail_gui.h"
|
||||
#include "road.h"
|
||||
#include "road_gui.h"
|
||||
#include "dropdown_type.h"
|
||||
#include "dropdown_func.h"
|
||||
#include "autoreplace_cmd.h"
|
||||
#include "group_cmd.h"
|
||||
#include "settings_cmd.h"
|
||||
#include "settings_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "vehicle_gui.h"
|
||||
#include "window_func.h"
|
||||
#include "window_gui.h"
|
||||
|
||||
#include "widgets/autoreplace_widget.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
@ -273,7 +273,7 @@ public:
|
|||
this->vehicle_type = vehicletype;
|
||||
this->engines[0].ForceRebuild();
|
||||
this->engines[1].ForceRebuild();
|
||||
this->details_height = ((vehicletype == VEH_TRAIN) ? 10 : 9);
|
||||
this->details_height = ((vehicletype == VEH_TRAIN) ? 10 : 9);
|
||||
this->sel_engine[0] = EngineID::Invalid();
|
||||
this->sel_engine[1] = EngineID::Invalid();
|
||||
this->show_hidden_engines = _engine_sort_show_hidden_engines[vehicletype];
|
||||
|
@ -475,7 +475,7 @@ public:
|
|||
* Either engines list is empty
|
||||
* or The selected replacement engine has a replacement (to prevent loops). */
|
||||
this->SetWidgetDisabledState(WID_RV_START_REPLACE,
|
||||
this->sel_engine[0] == EngineID::Invalid() || this->sel_engine[1] == EngineID::Invalid() || EngineReplacementForCompany(c, this->sel_engine[1], this->sel_group) != EngineID::Invalid());
|
||||
this->sel_engine[0] == EngineID::Invalid() || this->sel_engine[1] == EngineID::Invalid() || EngineReplacementForCompany(c, this->sel_engine[1], this->sel_group) != EngineID::Invalid());
|
||||
|
||||
/* Disable the "Stop Replacing" button if:
|
||||
* The left engines list (existing vehicle) is empty
|
||||
|
@ -495,8 +495,9 @@ public:
|
|||
ted.cost = 0;
|
||||
ted.FillDefaultCapacities(e);
|
||||
|
||||
const Rect r = this->GetWidget<NWidgetBase>(side == 0 ? WID_RV_LEFT_DETAILS : WID_RV_RIGHT_DETAILS)->GetCurrentRect()
|
||||
.Shrink(WidgetDimensions::scaled.frametext, WidgetDimensions::scaled.framerect);
|
||||
const Rect r = this->GetWidget<NWidgetBase>(side == 0 ? WID_RV_LEFT_DETAILS : WID_RV_RIGHT_DETAILS)
|
||||
->GetCurrentRect()
|
||||
.Shrink(WidgetDimensions::scaled.frametext, WidgetDimensions::scaled.framerect);
|
||||
int text_end = DrawVehiclePurchaseInfo(r.left, r.right, r.top, this->sel_engine[side], ted);
|
||||
needed_height = std::max(needed_height, (text_end - r.top) / GetCharacterHeight(FS_NORMAL));
|
||||
}
|
||||
|
@ -588,7 +589,10 @@ public:
|
|||
const auto it = this->vscroll[click_side]->GetScrolledItemFromWidget(this->engines[click_side], pt.y, this, widget);
|
||||
if (it != this->engines[click_side].end()) {
|
||||
const auto &item = *it;
|
||||
const Rect r = this->GetWidget<NWidgetBase>(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.matrix).WithWidth(WidgetDimensions::scaled.hsep_indent * (item.indent + 1), _current_text_dir == TD_RTL);
|
||||
const Rect r = this->GetWidget<NWidgetBase>(widget)
|
||||
->GetCurrentRect()
|
||||
.Shrink(WidgetDimensions::scaled.matrix)
|
||||
.WithWidth(WidgetDimensions::scaled.hsep_indent * (item.indent + 1), _current_text_dir == TD_RTL);
|
||||
if (item.flags.Test(EngineDisplayFlag::HasVariants) && IsInsideMM(r.left, r.right, pt.x)) {
|
||||
/* toggle folded flag on engine */
|
||||
assert(item.variant_id != EngineID::Invalid());
|
||||
|
@ -604,11 +608,10 @@ public:
|
|||
|
||||
/* If Ctrl is pressed on the left side and we don't have any engines of the selected type, stop autoreplacing.
|
||||
* This is most common when we have finished autoreplacing the engine and want to remove it from the list. */
|
||||
if (click_side == 0 && _ctrl_pressed && e != EngineID::Invalid() &&
|
||||
(GetGroupNumEngines(_local_company, sel_group, e) == 0 || GetGroupNumEngines(_local_company, ALL_GROUP, e) == 0)) {
|
||||
EngineID veh_from = e;
|
||||
Command<CMD_SET_AUTOREPLACE>::Post(this->sel_group, veh_from, EngineID::Invalid(), false);
|
||||
break;
|
||||
if (click_side == 0 && _ctrl_pressed && e != EngineID::Invalid() && (GetGroupNumEngines(_local_company, sel_group, e) == 0 || GetGroupNumEngines(_local_company, ALL_GROUP, e) == 0)) {
|
||||
EngineID veh_from = e;
|
||||
Command<CMD_SET_AUTOREPLACE>::Post(this->sel_group, veh_from, EngineID::Invalid(), false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (e == this->sel_engine[click_side]) break; // we clicked the one we already selected
|
||||
|
@ -758,12 +761,7 @@ static constexpr NWidgetPart _nested_replace_rail_vehicle_widgets[] = {
|
|||
};
|
||||
/* clang-format on */
|
||||
|
||||
static WindowDesc _replace_rail_vehicle_desc(
|
||||
WDP_AUTO, "replace_vehicle_train", 500, 140,
|
||||
WC_REPLACE_VEHICLE, WC_NONE,
|
||||
WindowDefaultFlag::Construction,
|
||||
_nested_replace_rail_vehicle_widgets
|
||||
);
|
||||
static WindowDesc _replace_rail_vehicle_desc(WDP_AUTO, "replace_vehicle_train", 500, 140, WC_REPLACE_VEHICLE, WC_NONE, WindowDefaultFlag::Construction, _nested_replace_rail_vehicle_widgets);
|
||||
|
||||
/* clang-format off */
|
||||
static constexpr NWidgetPart _nested_replace_road_vehicle_widgets[] = {
|
||||
|
@ -818,12 +816,7 @@ static constexpr NWidgetPart _nested_replace_road_vehicle_widgets[] = {
|
|||
};
|
||||
/* clang-format on */
|
||||
|
||||
static WindowDesc _replace_road_vehicle_desc(
|
||||
WDP_AUTO, "replace_vehicle_road", 500, 140,
|
||||
WC_REPLACE_VEHICLE, WC_NONE,
|
||||
WindowDefaultFlag::Construction,
|
||||
_nested_replace_road_vehicle_widgets
|
||||
);
|
||||
static WindowDesc _replace_road_vehicle_desc(WDP_AUTO, "replace_vehicle_road", 500, 140, WC_REPLACE_VEHICLE, WC_NONE, WindowDefaultFlag::Construction, _nested_replace_road_vehicle_widgets);
|
||||
|
||||
/* clang-format off */
|
||||
static constexpr NWidgetPart _nested_replace_vehicle_widgets[] = {
|
||||
|
@ -874,12 +867,7 @@ static constexpr NWidgetPart _nested_replace_vehicle_widgets[] = {
|
|||
};
|
||||
/* clang-format on */
|
||||
|
||||
static WindowDesc _replace_vehicle_desc(
|
||||
WDP_AUTO, "replace_vehicle", 456, 118,
|
||||
WC_REPLACE_VEHICLE, WC_NONE,
|
||||
WindowDefaultFlag::Construction,
|
||||
_nested_replace_vehicle_widgets
|
||||
);
|
||||
static WindowDesc _replace_vehicle_desc(WDP_AUTO, "replace_vehicle", 456, 118, WC_REPLACE_VEHICLE, WC_NONE, WindowDefaultFlag::Construction, _nested_replace_vehicle_widgets);
|
||||
|
||||
/**
|
||||
* Show the autoreplace configuration window for a particular group.
|
||||
|
@ -890,8 +878,14 @@ void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
|
|||
{
|
||||
CloseWindowById(WC_REPLACE_VEHICLE, vehicletype);
|
||||
switch (vehicletype) {
|
||||
case VEH_TRAIN: new ReplaceVehicleWindow(_replace_rail_vehicle_desc, vehicletype, id_g); break;
|
||||
case VEH_ROAD: new ReplaceVehicleWindow(_replace_road_vehicle_desc, vehicletype, id_g); break;
|
||||
default: new ReplaceVehicleWindow(_replace_vehicle_desc, vehicletype, id_g); break;
|
||||
case VEH_TRAIN:
|
||||
new ReplaceVehicleWindow(_replace_rail_vehicle_desc, vehicletype, id_g);
|
||||
break;
|
||||
case VEH_ROAD:
|
||||
new ReplaceVehicleWindow(_replace_road_vehicle_desc, vehicletype, id_g);
|
||||
break;
|
||||
default:
|
||||
new ReplaceVehicleWindow(_replace_vehicle_desc, vehicletype, id_g);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,8 +51,7 @@ inline bool AutoslopeCheckForEntranceEdge(TileIndex tile, int z_new, Slope tileh
|
|||
inline bool AutoslopeCheckForAxis(TileIndex tile, int z_new, Slope tileh_new, Axis axis)
|
||||
{
|
||||
DiagDirection direction = AxisToDiagDir(axis);
|
||||
return AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction) &&
|
||||
AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction));
|
||||
return AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction) && AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,9 +63,7 @@ inline bool AutoslopeCheckForAxis(TileIndex tile, int z_new, Slope tileh_new, Ax
|
|||
*/
|
||||
inline bool AutoslopeEnabled()
|
||||
{
|
||||
return (_settings_game.construction.autoslope &&
|
||||
(_current_company < MAX_COMPANIES ||
|
||||
(_current_company == OWNER_NONE && _game_mode == GM_EDITOR)));
|
||||
return (_settings_game.construction.autoslope && (_current_company < MAX_COMPANIES || (_current_company == OWNER_NONE && _game_mode == GM_EDITOR)));
|
||||
}
|
||||
|
||||
#endif /* AUTOSLOPE_H */
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
/** @file base_consist.cpp Properties for front vehicles/consists. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "base_consist.h"
|
||||
#include "vehicle_base.h"
|
||||
|
||||
#include "string_func.h"
|
||||
#include "vehicle_base.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
||||
/**
|
||||
* Copy properties of other BaseConsist.
|
||||
* @param src Source for copying
|
||||
|
|
|
@ -40,7 +40,7 @@ struct BaseConsist {
|
|||
|
||||
TimerGameTick::TickCounter depot_unbunching_last_departure{}; ///< When the vehicle last left its unbunching depot.
|
||||
TimerGameTick::TickCounter depot_unbunching_next_departure{}; ///< When the vehicle will next try to leave its unbunching depot.
|
||||
TimerGameTick::Ticks round_trip_time; ///< How many ticks for a single circumnavigation of the orders.
|
||||
TimerGameTick::Ticks round_trip_time; ///< How many ticks for a single circumnavigation of the orders.
|
||||
|
||||
uint16_t service_interval = 0; ///< The interval for (automatic) servicing; either in days or %.
|
||||
|
||||
|
|
|
@ -10,11 +10,12 @@
|
|||
#ifndef BASE_MEDIA_BASE_H
|
||||
#define BASE_MEDIA_BASE_H
|
||||
|
||||
#include "fileio_func.h"
|
||||
#include "textfile_type.h"
|
||||
#include "textfile_gui.h"
|
||||
#include "3rdparty/md5/md5.h"
|
||||
#include <unordered_map>
|
||||
#include "3rdparty/md5/md5.h"
|
||||
|
||||
#include "fileio_func.h"
|
||||
#include "textfile_gui.h"
|
||||
#include "textfile_type.h"
|
||||
|
||||
/* Forward declare these; can't do 'struct X' in functions as older GCCs barf on that */
|
||||
struct IniFile;
|
||||
|
@ -24,14 +25,14 @@ struct ContentInfo;
|
|||
struct MD5File {
|
||||
/** The result of a checksum check */
|
||||
enum ChecksumResult : uint8_t {
|
||||
CR_UNKNOWN, ///< The file has not been checked yet
|
||||
CR_MATCH, ///< The file did exist and the md5 checksum did match
|
||||
CR_UNKNOWN, ///< The file has not been checked yet
|
||||
CR_MATCH, ///< The file did exist and the md5 checksum did match
|
||||
CR_MISMATCH, ///< The file did exist, just the md5 checksum did not match
|
||||
CR_NO_FILE, ///< The file did not exist
|
||||
CR_NO_FILE, ///< The file did not exist
|
||||
};
|
||||
|
||||
std::string filename; ///< filename
|
||||
MD5Hash hash; ///< md5 sum of the file
|
||||
std::string filename; ///< filename
|
||||
MD5Hash hash; ///< md5 sum of the file
|
||||
std::string missing_warning; ///< warning when this file is missing
|
||||
ChecksumResult check_result; ///< cached result of md5 check
|
||||
|
||||
|
@ -39,7 +40,8 @@ struct MD5File {
|
|||
};
|
||||
|
||||
/** Defines the traits of a BaseSet type. */
|
||||
template <class T> struct BaseSetTraits;
|
||||
template <class T>
|
||||
struct BaseSetTraits;
|
||||
|
||||
/**
|
||||
* Information about a single base set.
|
||||
|
@ -58,8 +60,8 @@ struct BaseSet {
|
|||
/** BaseSet type name. */
|
||||
static constexpr std::string_view SET_TYPE = BaseSetTraits<T>::set_type;
|
||||
|
||||
std::string name; ///< The name of the base set
|
||||
std::string url; ///< URL for information about the base set
|
||||
std::string name; ///< The name of the base set
|
||||
std::string url; ///< URL for information about the base set
|
||||
TranslatedStrings description; ///< Description of the base set
|
||||
uint32_t shortname = 0; ///< Four letter short variant of the name
|
||||
uint32_t version = 0; ///< The version of this base set
|
||||
|
@ -97,6 +99,7 @@ struct BaseSet {
|
|||
}
|
||||
|
||||
bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename = true);
|
||||
|
||||
void CopyCompatibleConfig([[maybe_unused]] const T &src) {}
|
||||
|
||||
/**
|
||||
|
@ -177,6 +180,7 @@ protected:
|
|||
* @return the extension
|
||||
*/
|
||||
static const char *GetExtension();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Determine the graphics pack that has to be used.
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
|
||||
#include "base_media_base.h"
|
||||
#include "debug.h"
|
||||
#include "error_func.h"
|
||||
#include "ini_type.h"
|
||||
#include "string_func.h"
|
||||
#include "error_func.h"
|
||||
|
||||
extern void CheckExternalFiles();
|
||||
|
||||
|
@ -76,8 +76,8 @@ bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, con
|
|||
this->fallback = (item != nullptr && item->value && *item->value != "0" && *item->value != "false");
|
||||
|
||||
/* For each of the file types we want to find the file, MD5 checksums and warning messages. */
|
||||
const IniGroup *files = ini.GetGroup("files");
|
||||
const IniGroup *md5s = ini.GetGroup("md5s");
|
||||
const IniGroup *files = ini.GetGroup("files");
|
||||
const IniGroup *md5s = ini.GetGroup("md5s");
|
||||
const IniGroup *origin = ini.GetGroup("origin");
|
||||
auto file_names = BaseSet<T>::GetFilenames();
|
||||
|
||||
|
@ -169,7 +169,7 @@ bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_
|
|||
|
||||
Tbase_set *set = new Tbase_set();
|
||||
IniFile ini{};
|
||||
std::string path{ filename, basepath_length };
|
||||
std::string path{filename, basepath_length};
|
||||
ini.LoadFromDisk(path, BASESET_DIR);
|
||||
|
||||
auto psep = path.rfind(PATHSEPCHAR);
|
||||
|
@ -189,11 +189,9 @@ bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_
|
|||
}
|
||||
if (duplicate != nullptr) {
|
||||
/* The more complete set takes precedence over the version number. */
|
||||
if ((duplicate->valid_files == set->valid_files && duplicate->version >= set->version) ||
|
||||
duplicate->valid_files > set->valid_files) {
|
||||
Debug(grf, 1, "Not adding {} ({}) as base {} set (duplicate, {})", set->name, set->version,
|
||||
BaseSet<Tbase_set>::SET_TYPE,
|
||||
duplicate->valid_files > set->valid_files ? "less valid files" : "lower version");
|
||||
if ((duplicate->valid_files == set->valid_files && duplicate->version >= set->version) || duplicate->valid_files > set->valid_files) {
|
||||
Debug(grf, 1, "Not adding {} ({}) as base {} set (duplicate, {})", set->name, set->version, BaseSet<Tbase_set>::SET_TYPE,
|
||||
duplicate->valid_files > set->valid_files ? "less valid files" : "lower version");
|
||||
set->next = BaseMedia<Tbase_set>::duplicate_sets;
|
||||
BaseMedia<Tbase_set>::duplicate_sets = set;
|
||||
} else {
|
||||
|
@ -211,9 +209,8 @@ bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_
|
|||
* version number until a new game is started which isn't a big problem */
|
||||
if (BaseMedia<Tbase_set>::used_set == duplicate) BaseMedia<Tbase_set>::used_set = set;
|
||||
|
||||
Debug(grf, 1, "Removing {} ({}) as base {} set (duplicate, {})", duplicate->name, duplicate->version,
|
||||
BaseSet<Tbase_set>::SET_TYPE,
|
||||
duplicate->valid_files < set->valid_files ? "less valid files" : "lower version");
|
||||
Debug(grf, 1, "Removing {} ({}) as base {} set (duplicate, {})", duplicate->name, duplicate->version, BaseSet<Tbase_set>::SET_TYPE,
|
||||
duplicate->valid_files < set->valid_files ? "less valid files" : "lower version");
|
||||
duplicate->next = BaseMedia<Tbase_set>::duplicate_sets;
|
||||
BaseMedia<Tbase_set>::duplicate_sets = duplicate;
|
||||
ret = true;
|
||||
|
@ -319,7 +316,8 @@ template <class Tbase_set>
|
|||
|
||||
#include "network/core/tcp_content_type.h"
|
||||
|
||||
template <class Tbase_set> const char *TryGetBaseSetFile(const ContentInfo &ci, bool md5sum, const Tbase_set *s)
|
||||
template <class Tbase_set>
|
||||
const char *TryGetBaseSetFile(const ContentInfo &ci, bool md5sum, const Tbase_set *s)
|
||||
{
|
||||
for (; s != nullptr; s = s->next) {
|
||||
if (s->GetNumMissing() != 0) continue;
|
||||
|
@ -339,8 +337,7 @@ template <class Tbase_set> const char *TryGetBaseSetFile(const ContentInfo &ci,
|
|||
template <class Tbase_set>
|
||||
/* static */ bool BaseMedia<Tbase_set>::HasSet(const ContentInfo &ci, bool md5sum)
|
||||
{
|
||||
return (TryGetBaseSetFile(ci, md5sum, BaseMedia<Tbase_set>::available_sets) != nullptr) ||
|
||||
(TryGetBaseSetFile(ci, md5sum, BaseMedia<Tbase_set>::duplicate_sets) != nullptr);
|
||||
return (TryGetBaseSetFile(ci, md5sum, BaseMedia<Tbase_set>::available_sets) != nullptr) || (TryGetBaseSetFile(ci, md5sum, BaseMedia<Tbase_set>::duplicate_sets) != nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,24 +14,25 @@
|
|||
|
||||
/** Types of graphics in the base graphics set */
|
||||
enum GraphicsFileType : uint8_t {
|
||||
GFT_BASE, ///< Base sprites for all climates
|
||||
GFT_LOGOS, ///< Logos, landscape icons and original terrain generator sprites
|
||||
GFT_ARCTIC, ///< Landscape replacement sprites for arctic
|
||||
GFT_BASE, ///< Base sprites for all climates
|
||||
GFT_LOGOS, ///< Logos, landscape icons and original terrain generator sprites
|
||||
GFT_ARCTIC, ///< Landscape replacement sprites for arctic
|
||||
GFT_TROPICAL, ///< Landscape replacement sprites for tropical
|
||||
GFT_TOYLAND, ///< Landscape replacement sprites for toyland
|
||||
GFT_EXTRA, ///< Extra sprites that were not part of the original sprites
|
||||
MAX_GFT, ///< We are looking for this amount of GRFs
|
||||
GFT_TOYLAND, ///< Landscape replacement sprites for toyland
|
||||
GFT_EXTRA, ///< Extra sprites that were not part of the original sprites
|
||||
MAX_GFT, ///< We are looking for this amount of GRFs
|
||||
};
|
||||
|
||||
/** Blitter type for base graphics sets. */
|
||||
enum BlitterType : uint8_t {
|
||||
BLT_8BPP, ///< Base set has 8 bpp sprites only.
|
||||
BLT_32BPP, ///< Base set has both 8 bpp and 32 bpp sprites.
|
||||
BLT_8BPP, ///< Base set has 8 bpp sprites only.
|
||||
BLT_32BPP, ///< Base set has both 8 bpp and 32 bpp sprites.
|
||||
};
|
||||
|
||||
struct GRFConfig;
|
||||
|
||||
template <> struct BaseSetTraits<struct GraphicsSet> {
|
||||
template <>
|
||||
struct BaseSetTraits<struct GraphicsSet> {
|
||||
static constexpr size_t num_files = MAX_GFT;
|
||||
static constexpr bool search_in_tars = true;
|
||||
static constexpr std::string_view set_type = "graphics";
|
||||
|
@ -49,7 +50,12 @@ public:
|
|||
~GraphicsSet();
|
||||
|
||||
bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename);
|
||||
GRFConfig *GetExtraConfig() const { return this->extra_cfg.get(); }
|
||||
|
||||
GRFConfig *GetExtraConfig() const
|
||||
{
|
||||
return this->extra_cfg.get();
|
||||
}
|
||||
|
||||
GRFConfig &GetOrCreateExtraConfig() const;
|
||||
bool IsConfigurable() const;
|
||||
void CopyCompatibleConfig(const GraphicsSet &src);
|
||||
|
@ -63,10 +69,11 @@ public:
|
|||
/** Values loaded from config file. */
|
||||
struct Ini {
|
||||
std::string name;
|
||||
uint32_t shortname; ///< unique key for base set
|
||||
uint32_t extra_version; ///< version of the extra GRF
|
||||
uint32_t shortname; ///< unique key for base set
|
||||
uint32_t extra_version; ///< version of the extra GRF
|
||||
std::vector<uint32_t> extra_params; ///< parameters for the extra GRF
|
||||
};
|
||||
|
||||
static inline Ini ini_data;
|
||||
};
|
||||
|
||||
|
|
|
@ -13,14 +13,14 @@
|
|||
#include "base_media_base.h"
|
||||
|
||||
/** Maximum number of songs in the 'class' playlists. */
|
||||
static const uint NUM_SONGS_CLASS = 10;
|
||||
static const uint NUM_SONGS_CLASS = 10;
|
||||
/** Number of classes for songs */
|
||||
static const uint NUM_SONG_CLASSES = 3;
|
||||
static const uint NUM_SONG_CLASSES = 3;
|
||||
/** Maximum number of songs in the full playlist; theme song + the classes */
|
||||
static const uint NUM_SONGS_AVAILABLE = 1 + NUM_SONG_CLASSES * NUM_SONGS_CLASS;
|
||||
|
||||
/** Maximum number of songs in the (custom) playlist */
|
||||
static const uint NUM_SONGS_PLAYLIST = 32;
|
||||
static const uint NUM_SONGS_PLAYLIST = 32;
|
||||
|
||||
/* Functions to read DOS music CAT files, similar to but not quite the same as sound effect CAT files */
|
||||
std::optional<std::string> GetMusicCatEntryName(const std::string &filename, size_t entrynum);
|
||||
|
@ -28,22 +28,23 @@ std::optional<std::vector<uint8_t>> GetMusicCatEntryData(const std::string &file
|
|||
|
||||
enum MusicTrackType : uint8_t {
|
||||
MTT_STANDARDMIDI, ///< Standard MIDI file
|
||||
MTT_MPSMIDI, ///< MPS GM driver MIDI format (contained in a CAT file)
|
||||
MTT_MPSMIDI, ///< MPS GM driver MIDI format (contained in a CAT file)
|
||||
};
|
||||
|
||||
/** Metadata about a music track. */
|
||||
struct MusicSongInfo {
|
||||
std::string songname; ///< name of song displayed in UI
|
||||
uint8_t tracknr; ///< track number of song displayed in UI
|
||||
std::string filename; ///< file on disk containing song (when used in MusicSet class)
|
||||
std::string songname; ///< name of song displayed in UI
|
||||
uint8_t tracknr; ///< track number of song displayed in UI
|
||||
std::string filename; ///< file on disk containing song (when used in MusicSet class)
|
||||
MusicTrackType filetype; ///< decoder required for song file
|
||||
int cat_index; ///< entry index in CAT file, for filetype==MTT_MPSMIDI
|
||||
bool loop; ///< song should play in a tight loop if possible, never ending
|
||||
int override_start; ///< MIDI ticks to skip over in beginning
|
||||
int override_end; ///< MIDI tick to end the song at (0 if no override)
|
||||
int cat_index; ///< entry index in CAT file, for filetype==MTT_MPSMIDI
|
||||
bool loop; ///< song should play in a tight loop if possible, never ending
|
||||
int override_start; ///< MIDI ticks to skip over in beginning
|
||||
int override_end; ///< MIDI tick to end the song at (0 if no override)
|
||||
};
|
||||
|
||||
template <> struct BaseSetTraits<struct MusicSet> {
|
||||
template <>
|
||||
struct BaseSetTraits<struct MusicSet> {
|
||||
static constexpr size_t num_files = NUM_SONGS_AVAILABLE;
|
||||
static constexpr bool search_in_tars = false;
|
||||
static constexpr std::string_view set_type = "music";
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
|
||||
#include "base_media_base.h"
|
||||
|
||||
template <> struct BaseSetTraits<struct SoundsSet> {
|
||||
template <>
|
||||
struct BaseSetTraits<struct SoundsSet> {
|
||||
static constexpr size_t num_files = 1;
|
||||
static constexpr bool search_in_tars = true;
|
||||
static constexpr std::string_view set_type = "sounds";
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
|
||||
#include "core/pool_type.hpp"
|
||||
#include "command_type.h"
|
||||
#include "viewport_type.h"
|
||||
#include "station_map.h"
|
||||
#include "timer/timer_game_calendar.h"
|
||||
#include "viewport_type.h"
|
||||
|
||||
typedef Pool<BaseStation, StationID, 32> StationPool;
|
||||
extern StationPool _station_pool;
|
||||
|
@ -51,7 +51,7 @@ struct StationRect : public Rect {
|
|||
|
||||
static bool ScanForStationTiles(StationID st_id, int left_a, int top_a, int right_a, int bottom_a);
|
||||
|
||||
StationRect& operator = (const Rect &src);
|
||||
StationRect &operator=(const Rect &src);
|
||||
};
|
||||
|
||||
/** Base class for all station-ish types */
|
||||
|
@ -135,7 +135,6 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
|
|||
*/
|
||||
virtual void GetTileArea(TileArea *ta, StationType type) const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Obtain the length of a platform
|
||||
* @pre tile must be a rail station tile
|
||||
|
@ -194,8 +193,16 @@ private:
|
|||
bool SetRoadStopTileData(TileIndex tile, uint8_t data, bool animation);
|
||||
|
||||
public:
|
||||
inline void SetRoadStopRandomBits(TileIndex tile, uint8_t random_bits) { this->SetRoadStopTileData(tile, random_bits, false); }
|
||||
inline bool SetRoadStopAnimationFrame(TileIndex tile, uint8_t frame) { return this->SetRoadStopTileData(tile, frame, true); }
|
||||
inline void SetRoadStopRandomBits(TileIndex tile, uint8_t random_bits)
|
||||
{
|
||||
this->SetRoadStopTileData(tile, random_bits, false);
|
||||
}
|
||||
|
||||
inline bool SetRoadStopAnimationFrame(TileIndex tile, uint8_t frame)
|
||||
{
|
||||
return this->SetRoadStopTileData(tile, frame, true);
|
||||
}
|
||||
|
||||
void RemoveRoadStopTileData(TileIndex tile);
|
||||
|
||||
static void PostDestructor(size_t index);
|
||||
|
@ -216,8 +223,7 @@ struct SpecializedStation : public BaseStation {
|
|||
* Set station type correctly
|
||||
* @param tile The base tile of the station.
|
||||
*/
|
||||
inline SpecializedStation(TileIndex tile) :
|
||||
BaseStation(tile)
|
||||
inline SpecializedStation(TileIndex tile) : BaseStation(tile)
|
||||
{
|
||||
this->facilities = EXPECTED_FACIL;
|
||||
}
|
||||
|
@ -297,7 +303,10 @@ struct SpecializedStation : public BaseStation {
|
|||
* @param from index of the first station to consider
|
||||
* @return an iterable ensemble of all valid stations of type T
|
||||
*/
|
||||
static Pool::IterateWrapper<T> Iterate(size_t from = 0) { return Pool::IterateWrapper<T>(from); }
|
||||
static Pool::IterateWrapper<T> Iterate(size_t from = 0)
|
||||
{
|
||||
return Pool::IterateWrapper<T>(from);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -306,8 +315,19 @@ struct SpecializedStation : public BaseStation {
|
|||
* @param bst Station of custom spec list.
|
||||
* @return Speclist of custom spec type.
|
||||
*/
|
||||
template <class T> std::vector<SpecMapping<T>> &GetStationSpecList(BaseStation *bst);
|
||||
template <> inline std::vector<SpecMapping<StationSpec>> &GetStationSpecList<StationSpec>(BaseStation *bst) { return bst->speclist; }
|
||||
template <> inline std::vector<SpecMapping<RoadStopSpec>> &GetStationSpecList<RoadStopSpec>(BaseStation *bst) { return bst->roadstop_speclist; }
|
||||
template <class T>
|
||||
std::vector<SpecMapping<T>> &GetStationSpecList(BaseStation *bst);
|
||||
|
||||
template <>
|
||||
inline std::vector<SpecMapping<StationSpec>> &GetStationSpecList<StationSpec>(BaseStation *bst)
|
||||
{
|
||||
return bst->speclist;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::vector<SpecMapping<RoadStopSpec>> &GetStationSpecList<RoadStopSpec>(BaseStation *bst)
|
||||
{
|
||||
return bst->roadstop_speclist;
|
||||
}
|
||||
|
||||
#endif /* BASE_STATION_BASE_H */
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#ifndef BITMAP_TYPE_HPP
|
||||
#define BITMAP_TYPE_HPP
|
||||
|
||||
|
||||
/** Represents a tile area containing containing individually set tiles.
|
||||
* Each tile must be contained within the preallocated area.
|
||||
* A std::vector<bool> is used to mark which tiles are contained.
|
||||
|
@ -19,9 +18,15 @@ class BitmapTileArea : public TileArea {
|
|||
protected:
|
||||
std::vector<bool> data;
|
||||
|
||||
inline uint Index(uint x, uint y) const { return y * this->w + x; }
|
||||
inline uint Index(uint x, uint y) const
|
||||
{
|
||||
return y * this->w + x;
|
||||
}
|
||||
|
||||
inline uint Index(TileIndex tile) const { return Index(TileX(tile) - TileX(this->tile), TileY(tile) - TileY(this->tile)); }
|
||||
inline uint Index(TileIndex tile) const
|
||||
{
|
||||
return Index(TileX(tile) - TileX(this->tile), TileY(tile) - TileY(this->tile));
|
||||
}
|
||||
|
||||
public:
|
||||
BitmapTileArea()
|
||||
|
@ -106,6 +111,7 @@ public:
|
|||
class BitmapTileIterator : public OrthogonalTileIterator {
|
||||
protected:
|
||||
const BitmapTileArea *bitmap;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct the iterator.
|
||||
|
@ -116,7 +122,7 @@ public:
|
|||
if (!this->bitmap->HasTile(TileIndex(this->tile))) ++(*this);
|
||||
}
|
||||
|
||||
inline TileIterator& operator ++() override
|
||||
inline TileIterator &operator++() override
|
||||
{
|
||||
(*this).OrthogonalTileIterator::operator++();
|
||||
while (this->tile != INVALID_TILE && !this->bitmap->HasTile(TileIndex(this->tile))) {
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
/** @file 32bpp_anim.cpp Implementation of the optimized 32 bpp blitter with animation support. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../video/video_driver.hpp"
|
||||
#include "../palette_func.h"
|
||||
|
||||
#include "32bpp_anim.hpp"
|
||||
|
||||
#include "../palette_func.h"
|
||||
#include "../video/video_driver.hpp"
|
||||
#include "common.hpp"
|
||||
|
||||
#include "../table/sprites.h"
|
||||
|
@ -26,11 +28,11 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
const SpriteData *src = (const SpriteData *)bp->sprite;
|
||||
|
||||
const Colour *src_px = (const Colour *)(src->data + src->offset[zoom][0]);
|
||||
const uint16_t *src_n = (const uint16_t *)(src->data + src->offset[zoom][1]);
|
||||
const uint16_t *src_n = (const uint16_t *)(src->data + src->offset[zoom][1]);
|
||||
|
||||
for (uint i = bp->skip_top; i != 0; i--) {
|
||||
src_px = (const Colour *)((const uint8_t *)src_px + *(const uint32_t *)src_px);
|
||||
src_n = (const uint16_t *)((const uint8_t *)src_n + *(const uint32_t *)src_n);
|
||||
src_n = (const uint16_t *)((const uint8_t *)src_n + *(const uint32_t *)src_n);
|
||||
}
|
||||
|
||||
Colour *dst = (Colour *)bp->dst + bp->top * bp->pitch + bp->left;
|
||||
|
@ -57,7 +59,7 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
|
||||
if (src_px->a == 0) {
|
||||
dst += n;
|
||||
src_px ++;
|
||||
src_px++;
|
||||
src_n++;
|
||||
|
||||
if (dst > dst_end) anim += dst - dst_end;
|
||||
|
@ -95,7 +97,7 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
continue;
|
||||
}
|
||||
|
||||
draw:;
|
||||
draw:;
|
||||
|
||||
switch (mode) {
|
||||
case BlitterMode::ColourRemap:
|
||||
|
@ -175,7 +177,6 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
}
|
||||
break;
|
||||
|
||||
|
||||
case BlitterMode::BlackRemap:
|
||||
do {
|
||||
*dst++ = Colour(0, 0, 0);
|
||||
|
@ -257,7 +258,7 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
anim = anim_ln;
|
||||
dst = dst_ln;
|
||||
src_px = src_px_ln;
|
||||
src_n = src_n_ln;
|
||||
src_n = src_n_ln;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,13 +271,26 @@ void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomL
|
|||
}
|
||||
|
||||
switch (mode) {
|
||||
default: NOT_REACHED();
|
||||
case BlitterMode::Normal: Draw<BlitterMode::Normal>(bp, zoom); return;
|
||||
case BlitterMode::ColourRemap: Draw<BlitterMode::ColourRemap>(bp, zoom); return;
|
||||
case BlitterMode::Transparent: Draw<BlitterMode::Transparent>(bp, zoom); return;
|
||||
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap>(bp, zoom); return;
|
||||
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap>(bp, zoom); return;
|
||||
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap>(bp, zoom); return;
|
||||
default:
|
||||
NOT_REACHED();
|
||||
case BlitterMode::Normal:
|
||||
Draw<BlitterMode::Normal>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::ColourRemap:
|
||||
Draw<BlitterMode::ColourRemap>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::Transparent:
|
||||
Draw<BlitterMode::Transparent>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::TransparentRemap:
|
||||
Draw<BlitterMode::TransparentRemap>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::CrashRemap:
|
||||
Draw<BlitterMode::CrashRemap>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::BlackRemap:
|
||||
Draw<BlitterMode::BlackRemap>(bp, zoom);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,12 +349,12 @@ void Blitter_32bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int
|
|||
{
|
||||
const Colour c = LookupColourInPalette(colour);
|
||||
|
||||
if (_screen_disable_anim) {
|
||||
if (_screen_disable_anim) {
|
||||
this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [&](int x, int y) {
|
||||
*((Colour *)video + x + y * _screen.pitch) = c;
|
||||
});
|
||||
} else {
|
||||
uint16_t * const offset_anim_buf = this->anim_buf + this->ScreenToAnimOffset((uint32_t *)video);
|
||||
uint16_t *const offset_anim_buf = this->anim_buf + this->ScreenToAnimOffset((uint32_t *)video);
|
||||
const uint16_t anim_colour = colour | (DEFAULT_BRIGHTNESS << 8);
|
||||
this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [&](int x, int y) {
|
||||
*((Colour *)video + x + y * _screen.pitch) = c;
|
||||
|
@ -511,8 +525,8 @@ void Blitter_32bppAnim::PaletteAnimate(const Palette &palette)
|
|||
const int width = this->anim_buf_width;
|
||||
const int pitch_offset = _screen.pitch - width;
|
||||
const int anim_pitch_offset = this->anim_buf_pitch - width;
|
||||
for (int y = this->anim_buf_height; y != 0 ; y--) {
|
||||
for (int x = width; x != 0 ; x--) {
|
||||
for (int y = this->anim_buf_height; y != 0; y--) {
|
||||
for (int x = width; x != 0; x--) {
|
||||
uint16_t value = *anim;
|
||||
uint8_t colour = GB(value, 0, 8);
|
||||
if (colour >= PALETTE_ANIM_START) {
|
||||
|
@ -537,8 +551,7 @@ Blitter::PaletteAnimation Blitter_32bppAnim::UsePaletteAnimation()
|
|||
|
||||
void Blitter_32bppAnim::PostResize()
|
||||
{
|
||||
if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height ||
|
||||
_screen.pitch != this->anim_buf_pitch) {
|
||||
if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height || _screen.pitch != this->anim_buf_pitch) {
|
||||
/* The size of the screen changed; we can assume we can wipe all data from our buffer */
|
||||
this->anim_buf_width = _screen.width;
|
||||
this->anim_buf_height = _screen.height;
|
||||
|
|
|
@ -15,19 +15,15 @@
|
|||
/** The optimised 32 bpp blitter with palette animation. */
|
||||
class Blitter_32bppAnim : public Blitter_32bppOptimized {
|
||||
protected:
|
||||
uint16_t *anim_buf; ///< In this buffer we keep track of the 8bpp indexes so we can do palette animation
|
||||
uint16_t *anim_buf; ///< In this buffer we keep track of the 8bpp indexes so we can do palette animation
|
||||
std::unique_ptr<uint16_t[]> anim_alloc; ///< The raw allocated buffer, not necessarily aligned correctly
|
||||
int anim_buf_width; ///< The width of the animation buffer.
|
||||
int anim_buf_width; ///< The width of the animation buffer.
|
||||
int anim_buf_height; ///< The height of the animation buffer.
|
||||
int anim_buf_pitch; ///< The pitch of the animation buffer (width rounded up to 16 byte boundary).
|
||||
Palette palette; ///< The current palette.
|
||||
int anim_buf_pitch; ///< The pitch of the animation buffer (width rounded up to 16 byte boundary).
|
||||
Palette palette; ///< The current palette.
|
||||
|
||||
public:
|
||||
Blitter_32bppAnim() :
|
||||
anim_buf(nullptr),
|
||||
anim_buf_width(0),
|
||||
anim_buf_height(0),
|
||||
anim_buf_pitch(0)
|
||||
Blitter_32bppAnim() : anim_buf(nullptr), anim_buf_width(0), anim_buf_height(0), anim_buf_pitch(0)
|
||||
{
|
||||
this->palette = _cur_palette;
|
||||
}
|
||||
|
@ -44,7 +40,11 @@ public:
|
|||
void PaletteAnimate(const Palette &palette) override;
|
||||
Blitter::PaletteAnimation UsePaletteAnimation() override;
|
||||
|
||||
std::string_view GetName() override { return "32bpp-anim"; }
|
||||
std::string_view GetName() override
|
||||
{
|
||||
return "32bpp-anim";
|
||||
}
|
||||
|
||||
void PostResize() override;
|
||||
|
||||
/**
|
||||
|
@ -64,14 +64,19 @@ public:
|
|||
return across + (lines * this->anim_buf_pitch);
|
||||
}
|
||||
|
||||
template <BlitterMode mode> void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
||||
template <BlitterMode mode>
|
||||
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
||||
};
|
||||
|
||||
/** Factory for the 32bpp blitter with animation. */
|
||||
class FBlitter_32bppAnim : public BlitterFactory {
|
||||
public:
|
||||
FBlitter_32bppAnim() : BlitterFactory("32bpp-anim", "32bpp Animation Blitter (palette animation)") {}
|
||||
std::unique_ptr<Blitter> CreateInstance() override { return std::make_unique<Blitter_32bppAnim>(); }
|
||||
|
||||
std::unique_ptr<Blitter> CreateInstance() override
|
||||
{
|
||||
return std::make_unique<Blitter_32bppAnim>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* BLITTER_32BPP_ANIM_HPP */
|
||||
|
|
|
@ -9,17 +9,20 @@
|
|||
|
||||
#ifdef WITH_SSE
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../video/video_driver.hpp"
|
||||
#include "32bpp_anim_sse2.hpp"
|
||||
#include "32bpp_sse_func.hpp"
|
||||
# include "../stdafx.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
# include "32bpp_anim_sse2.hpp"
|
||||
|
||||
# include "../video/video_driver.hpp"
|
||||
# include "32bpp_sse_func.hpp"
|
||||
|
||||
# include "../safeguards.h"
|
||||
|
||||
/** Instantiation of the partially SSSE2 32bpp with animation blitter factory. */
|
||||
static FBlitter_32bppSSE2_Anim iFBlitter_32bppSSE2_Anim;
|
||||
|
||||
GNU_TARGET("sse2")
|
||||
|
||||
void Blitter_32bppSSE2_Anim::PaletteAnimate(const Palette &palette)
|
||||
{
|
||||
assert(!_screen_disable_anim);
|
||||
|
@ -42,12 +45,12 @@ void Blitter_32bppSSE2_Anim::PaletteAnimate(const Palette &palette)
|
|||
__m128i anim_cmp = _mm_set1_epi16(PALETTE_ANIM_START - 1);
|
||||
__m128i brightness_cmp = _mm_set1_epi16(DEFAULT_BRIGHTNESS);
|
||||
__m128i colour_mask = _mm_set1_epi16(0xFF);
|
||||
for (int y = this->anim_buf_height; y != 0 ; y--) {
|
||||
for (int y = this->anim_buf_height; y != 0; y--) {
|
||||
Colour *next_dst_ln = dst + screen_pitch;
|
||||
const uint16_t *next_anim_ln = anim + anim_pitch;
|
||||
int x = width;
|
||||
while (x > 0) {
|
||||
__m128i data = _mm_load_si128((const __m128i *) anim);
|
||||
__m128i data = _mm_load_si128((const __m128i *)anim);
|
||||
|
||||
/* low bytes only, shifted into high positions */
|
||||
__m128i colour_data = _mm_and_si128(data, colour_mask);
|
||||
|
@ -56,10 +59,9 @@ void Blitter_32bppSSE2_Anim::PaletteAnimate(const Palette &palette)
|
|||
int colour_cmp_result = _mm_movemask_epi8(_mm_cmpgt_epi16(colour_data, anim_cmp));
|
||||
if (colour_cmp_result) {
|
||||
/* test if any brightness is unexpected */
|
||||
if (x < 8 || colour_cmp_result != 0xFFFF ||
|
||||
_mm_movemask_epi8(_mm_cmpeq_epi16(_mm_srli_epi16(data, 8), brightness_cmp)) != 0xFFFF) {
|
||||
if (x < 8 || colour_cmp_result != 0xFFFF || _mm_movemask_epi8(_mm_cmpeq_epi16(_mm_srli_epi16(data, 8), brightness_cmp)) != 0xFFFF) {
|
||||
/* slow path: < 8 pixels left or unexpected brightnesses */
|
||||
for (int z = std::min<int>(x, 8); z != 0 ; z--) {
|
||||
for (int z = std::min<int>(x, 8); z != 0; z--) {
|
||||
int value = _mm_extract_epi16(data, 0);
|
||||
uint8_t colour = GB(value, 0, 8);
|
||||
if (colour >= PALETTE_ANIM_START) {
|
||||
|
|
|
@ -12,33 +12,41 @@
|
|||
|
||||
#ifdef WITH_SSE
|
||||
|
||||
#ifndef SSE_VERSION
|
||||
#define SSE_VERSION 2
|
||||
#endif
|
||||
# ifndef SSE_VERSION
|
||||
# define SSE_VERSION 2
|
||||
# endif
|
||||
|
||||
#ifndef SSE_TARGET
|
||||
#define SSE_TARGET "sse2"
|
||||
#endif
|
||||
# ifndef SSE_TARGET
|
||||
# define SSE_TARGET "sse2"
|
||||
# endif
|
||||
|
||||
#ifndef FULL_ANIMATION
|
||||
#define FULL_ANIMATION 1
|
||||
#endif
|
||||
# ifndef FULL_ANIMATION
|
||||
# define FULL_ANIMATION 1
|
||||
# endif
|
||||
|
||||
#include "32bpp_anim.hpp"
|
||||
#include "32bpp_sse2.hpp"
|
||||
# include "32bpp_anim.hpp"
|
||||
# include "32bpp_sse2.hpp"
|
||||
|
||||
/** A partially 32 bpp blitter with palette animation. */
|
||||
class Blitter_32bppSSE2_Anim : public Blitter_32bppAnim {
|
||||
public:
|
||||
void PaletteAnimate(const Palette &palette) override;
|
||||
std::string_view GetName() override { return "32bpp-sse2-anim"; }
|
||||
|
||||
std::string_view GetName() override
|
||||
{
|
||||
return "32bpp-sse2-anim";
|
||||
}
|
||||
};
|
||||
|
||||
/** Factory for the partially 32bpp blitter with animation. */
|
||||
class FBlitter_32bppSSE2_Anim : public BlitterFactory {
|
||||
public:
|
||||
FBlitter_32bppSSE2_Anim() : BlitterFactory("32bpp-sse2-anim", "32bpp partially SSE2 Animation Blitter (palette animation)", HasCPUIDFlag(1, 3, 26)) {}
|
||||
std::unique_ptr<Blitter> CreateInstance() override { return std::make_unique<Blitter_32bppSSE2_Anim>(); }
|
||||
|
||||
std::unique_ptr<Blitter> CreateInstance() override
|
||||
{
|
||||
return std::make_unique<Blitter_32bppSSE2_Anim>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* WITH_SSE */
|
||||
|
|
|
@ -9,14 +9,17 @@
|
|||
|
||||
#ifdef WITH_SSE
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../palette_func.h"
|
||||
#include "../video/video_driver.hpp"
|
||||
#include "../table/sprites.h"
|
||||
#include "32bpp_anim_sse4.hpp"
|
||||
#include "32bpp_sse_func.hpp"
|
||||
# include "../stdafx.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
# include "32bpp_anim_sse4.hpp"
|
||||
|
||||
# include "../palette_func.h"
|
||||
# include "../video/video_driver.hpp"
|
||||
# include "32bpp_sse_func.hpp"
|
||||
|
||||
# include "../table/sprites.h"
|
||||
|
||||
# include "../safeguards.h"
|
||||
|
||||
/** Instantiation of the SSE4 32bpp blitter factory. */
|
||||
static FBlitter_32bppSSE4_Anim iFBlitter_32bppSSE4_Anim;
|
||||
|
@ -33,16 +36,16 @@ template <BlitterMode mode, Blitter_32bppSSE2::ReadMode read_mode, Blitter_32bpp
|
|||
GNU_TARGET("sse4.1")
|
||||
inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom)
|
||||
{
|
||||
const uint8_t * const remap = bp->remap;
|
||||
Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left;
|
||||
const uint8_t *const remap = bp->remap;
|
||||
Colour *dst_line = (Colour *)bp->dst + bp->top * bp->pitch + bp->left;
|
||||
uint16_t *anim_line = this->anim_buf + this->ScreenToAnimOffset((uint32_t *)bp->dst) + bp->top * this->anim_buf_pitch + bp->left;
|
||||
int effective_width = bp->width;
|
||||
|
||||
/* Find where to start reading in the source sprite. */
|
||||
const Blitter_32bppSSE_Base::SpriteData * const sd = (const Blitter_32bppSSE_Base::SpriteData *) bp->sprite;
|
||||
const SpriteInfo * const si = &sd->infos[zoom];
|
||||
const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width;
|
||||
const Colour *src_rgba_line = (const Colour *) ((const uint8_t *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size);
|
||||
const Blitter_32bppSSE_Base::SpriteData *const sd = (const Blitter_32bppSSE_Base::SpriteData *)bp->sprite;
|
||||
const SpriteInfo *const si = &sd->infos[zoom];
|
||||
const MapValue *src_mv_line = (const MapValue *)&sd->data[si->mv_offset] + bp->skip_top * si->sprite_width;
|
||||
const Colour *src_rgba_line = (const Colour *)((const uint8_t *)&sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size);
|
||||
|
||||
if (read_mode != RM_WITH_MARGIN) {
|
||||
src_rgba_line += bp->skip_left;
|
||||
|
@ -51,10 +54,10 @@ inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom
|
|||
const MapValue *src_mv = src_mv_line;
|
||||
|
||||
/* Load these variables into register before loop. */
|
||||
const __m128i a_cm = ALPHA_CONTROL_MASK;
|
||||
const __m128i a_cm = ALPHA_CONTROL_MASK;
|
||||
const __m128i pack_low_cm = PACK_LOW_CONTROL_MASK;
|
||||
const __m128i tr_nom_base = TRANSPARENT_NOM_BASE;
|
||||
const __m128i a_am = ALPHA_AND_MASK;
|
||||
const __m128i a_am = ALPHA_AND_MASK;
|
||||
|
||||
for (int y = bp->height; y != 0; y--) {
|
||||
Colour *dst = dst_line;
|
||||
|
@ -69,8 +72,8 @@ inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom
|
|||
dst += src_rgba_line[0].data;
|
||||
if (mode != BlitterMode::Transparent) src_mv += src_rgba_line[0].data;
|
||||
const int width_diff = si->sprite_width - bp->width;
|
||||
effective_width = bp->width - (int) src_rgba_line[0].data;
|
||||
const int delta_diff = (int) src_rgba_line[1].data - width_diff;
|
||||
effective_width = bp->width - (int)src_rgba_line[0].data;
|
||||
const int delta_diff = (int)src_rgba_line[1].data - width_diff;
|
||||
const int new_width = effective_width - delta_diff;
|
||||
effective_width = delta_diff > 0 ? new_width : effective_width;
|
||||
if (effective_width <= 0) goto next_line;
|
||||
|
@ -79,10 +82,10 @@ inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom
|
|||
switch (mode) {
|
||||
default:
|
||||
if (!translucent) {
|
||||
for (uint x = (uint) effective_width; x > 0; x--) {
|
||||
for (uint x = (uint)effective_width; x > 0; x--) {
|
||||
if (src->a) {
|
||||
if (animated) {
|
||||
*anim = *(const uint16_t*) src_mv;
|
||||
*anim = *(const uint16_t *)src_mv;
|
||||
*dst = (src_mv->m >= PALETTE_ANIM_START) ? AdjustBrightneSSE(this->LookupColourInPalette(src_mv->m), src_mv->v) : src->data;
|
||||
} else {
|
||||
*anim = 0;
|
||||
|
@ -97,22 +100,22 @@ inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom
|
|||
break;
|
||||
}
|
||||
|
||||
for (uint x = (uint) effective_width/2; x != 0; x--) {
|
||||
uint32_t mvX2 = *((uint32_t *) const_cast<MapValue *>(src_mv));
|
||||
__m128i srcABCD = _mm_loadl_epi64((const __m128i*) src);
|
||||
__m128i dstABCD = _mm_loadl_epi64((__m128i*) dst);
|
||||
for (uint x = (uint)effective_width / 2; x != 0; x--) {
|
||||
uint32_t mvX2 = *((uint32_t *)const_cast<MapValue *>(src_mv));
|
||||
__m128i srcABCD = _mm_loadl_epi64((const __m128i *)src);
|
||||
__m128i dstABCD = _mm_loadl_epi64((__m128i *)dst);
|
||||
|
||||
if (animated) {
|
||||
/* Remap colours. */
|
||||
const uint8_t m0 = mvX2;
|
||||
if (m0 >= PALETTE_ANIM_START) {
|
||||
const Colour c0 = (this->LookupColourInPalette(m0).data & 0x00FFFFFF) | (src[0].data & 0xFF000000);
|
||||
InsertFirstUint32(AdjustBrightneSSE(c0, (uint8_t) (mvX2 >> 8)).data, srcABCD);
|
||||
InsertFirstUint32(AdjustBrightneSSE(c0, (uint8_t)(mvX2 >> 8)).data, srcABCD);
|
||||
}
|
||||
const uint8_t m1 = mvX2 >> 16;
|
||||
if (m1 >= PALETTE_ANIM_START) {
|
||||
const Colour c1 = (this->LookupColourInPalette(m1).data & 0x00FFFFFF) | (src[1].data & 0xFF000000);
|
||||
InsertSecondUint32(AdjustBrightneSSE(c1, (uint8_t) (mvX2 >> 24)).data, srcABCD);
|
||||
InsertSecondUint32(AdjustBrightneSSE(c1, (uint8_t)(mvX2 >> 24)).data, srcABCD);
|
||||
}
|
||||
|
||||
/* Update anim buffer. */
|
||||
|
@ -121,23 +124,23 @@ inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom
|
|||
uint32_t anim01 = 0;
|
||||
if (a0 == 255) {
|
||||
if (a1 == 255) {
|
||||
*(uint32_t*) anim = mvX2;
|
||||
*(uint32_t *)anim = mvX2;
|
||||
goto bmno_full_opacity;
|
||||
}
|
||||
anim01 = (uint16_t) mvX2;
|
||||
anim01 = (uint16_t)mvX2;
|
||||
} else if (a0 == 0) {
|
||||
if (a1 == 0) {
|
||||
goto bmno_full_transparency;
|
||||
} else {
|
||||
if (a1 == 255) anim[1] = (uint16_t) (mvX2 >> 16);
|
||||
if (a1 == 255) anim[1] = (uint16_t)(mvX2 >> 16);
|
||||
goto bmno_alpha_blend;
|
||||
}
|
||||
}
|
||||
if (a1 > 0) {
|
||||
if (a1 == 255) anim01 |= mvX2 & 0xFFFF0000;
|
||||
*(uint32_t*) anim = anim01;
|
||||
*(uint32_t *)anim = anim01;
|
||||
} else {
|
||||
anim[0] = (uint16_t) anim01;
|
||||
anim[0] = (uint16_t)anim01;
|
||||
}
|
||||
} else {
|
||||
if (src[0].a) anim[0] = 0;
|
||||
|
@ -145,11 +148,11 @@ inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom
|
|||
}
|
||||
|
||||
/* Blend colours. */
|
||||
bmno_alpha_blend:
|
||||
bmno_alpha_blend:
|
||||
srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm, a_am);
|
||||
bmno_full_opacity:
|
||||
_mm_storel_epi64((__m128i *) dst, srcABCD);
|
||||
bmno_full_transparency:
|
||||
bmno_full_opacity:
|
||||
_mm_storel_epi64((__m128i *)dst, srcABCD);
|
||||
bmno_full_transparency:
|
||||
src_mv += 2;
|
||||
src += 2;
|
||||
anim += 2;
|
||||
|
@ -160,7 +163,7 @@ bmno_full_transparency:
|
|||
if (src->a == 0) {
|
||||
/* Complete transparency. */
|
||||
} else if (src->a == 255) {
|
||||
*anim = *(const uint16_t*) src_mv;
|
||||
*anim = *(const uint16_t *)src_mv;
|
||||
*dst = (src_mv->m >= PALETTE_ANIM_START) ? AdjustBrightneSSE(LookupColourInPalette(src_mv->m), src_mv->v) : *src;
|
||||
} else {
|
||||
*anim = 0;
|
||||
|
@ -179,19 +182,19 @@ bmno_full_transparency:
|
|||
break;
|
||||
|
||||
case BlitterMode::ColourRemap:
|
||||
for (uint x = (uint) effective_width / 2; x != 0; x--) {
|
||||
uint32_t mvX2 = *((uint32_t *) const_cast<MapValue *>(src_mv));
|
||||
__m128i srcABCD = _mm_loadl_epi64((const __m128i*) src);
|
||||
__m128i dstABCD = _mm_loadl_epi64((__m128i*) dst);
|
||||
for (uint x = (uint)effective_width / 2; x != 0; x--) {
|
||||
uint32_t mvX2 = *((uint32_t *)const_cast<MapValue *>(src_mv));
|
||||
__m128i srcABCD = _mm_loadl_epi64((const __m128i *)src);
|
||||
__m128i dstABCD = _mm_loadl_epi64((__m128i *)dst);
|
||||
|
||||
/* Remap colours. */
|
||||
const uint m0 = (uint8_t) mvX2;
|
||||
const uint m0 = (uint8_t)mvX2;
|
||||
const uint r0 = remap[m0];
|
||||
const uint m1 = (uint8_t) (mvX2 >> 16);
|
||||
const uint m1 = (uint8_t)(mvX2 >> 16);
|
||||
const uint r1 = remap[m1];
|
||||
if (mvX2 & 0x00FF00FF) {
|
||||
/* Written so the compiler uses CMOV. */
|
||||
#define CMOV_REMAP(m_colour, m_colour_init, m_src, m_m) \
|
||||
/* Written so the compiler uses CMOV. */
|
||||
# define CMOV_REMAP(m_colour, m_colour_init, m_src, m_m) \
|
||||
Colour m_colour = m_colour_init; \
|
||||
{ \
|
||||
const Colour srcm = (Colour) (m_src); \
|
||||
|
@ -201,7 +204,7 @@ bmno_full_transparency:
|
|||
m_colour = r == 0 ? m_colour : cmap; \
|
||||
m_colour = m != 0 ? m_colour : srcm; \
|
||||
}
|
||||
#ifdef POINTER_IS_64BIT
|
||||
# ifdef POINTER_IS_64BIT
|
||||
uint64_t srcs = _mm_cvtsi128_si64(srcABCD);
|
||||
uint64_t dsts;
|
||||
if (animated) dsts = _mm_cvtsi128_si64(dstABCD);
|
||||
|
@ -209,16 +212,16 @@ bmno_full_transparency:
|
|||
CMOV_REMAP(c0, animated ? dsts : 0, srcs, mvX2);
|
||||
remapped_src = c0.data;
|
||||
CMOV_REMAP(c1, animated ? dsts >> 32 : 0, srcs >> 32, mvX2 >> 16);
|
||||
remapped_src |= (uint64_t) c1.data << 32;
|
||||
remapped_src |= (uint64_t)c1.data << 32;
|
||||
srcABCD = _mm_cvtsi64_si128(remapped_src);
|
||||
#else
|
||||
# else
|
||||
Colour remapped_src[2];
|
||||
CMOV_REMAP(c0, animated ? _mm_cvtsi128_si32(dstABCD) : 0, _mm_cvtsi128_si32(srcABCD), mvX2);
|
||||
remapped_src[0] = c0.data;
|
||||
CMOV_REMAP(c1, animated ? dst[1] : 0, src[1], mvX2 >> 16);
|
||||
remapped_src[1] = c1.data;
|
||||
srcABCD = _mm_loadl_epi64((__m128i*) &remapped_src);
|
||||
#endif
|
||||
srcABCD = _mm_loadl_epi64((__m128i *)&remapped_src);
|
||||
# endif
|
||||
|
||||
if ((mvX2 & 0xFF00FF00) != 0x80008000) srcABCD = AdjustBrightnessOfTwoPixels(srcABCD, mvX2);
|
||||
}
|
||||
|
@ -231,7 +234,7 @@ bmno_full_transparency:
|
|||
if (a0 == 255) {
|
||||
anim01 |= r0;
|
||||
if (a1 == 255) {
|
||||
*(uint32_t*) anim = anim01 | (r1 << 16);
|
||||
*(uint32_t *)anim = anim01 | (r1 << 16);
|
||||
goto bmcr_full_opacity;
|
||||
}
|
||||
} else if (a0 == 0) {
|
||||
|
@ -246,9 +249,9 @@ bmno_full_transparency:
|
|||
}
|
||||
if (a1 > 0) {
|
||||
if (a1 == 255) anim01 |= r1 << 16;
|
||||
*(uint32_t*) anim = anim01;
|
||||
*(uint32_t *)anim = anim01;
|
||||
} else {
|
||||
anim[0] = (uint16_t) anim01;
|
||||
anim[0] = (uint16_t)anim01;
|
||||
}
|
||||
} else {
|
||||
if (src[0].a) anim[0] = 0;
|
||||
|
@ -256,11 +259,11 @@ bmno_full_transparency:
|
|||
}
|
||||
|
||||
/* Blend colours. */
|
||||
bmcr_alpha_blend:
|
||||
bmcr_alpha_blend:
|
||||
srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm, a_am);
|
||||
bmcr_full_opacity:
|
||||
_mm_storel_epi64((__m128i *) dst, srcABCD);
|
||||
bmcr_full_transparency:
|
||||
bmcr_full_opacity:
|
||||
_mm_storel_epi64((__m128i *)dst, srcABCD);
|
||||
bmcr_full_transparency:
|
||||
src_mv += 2;
|
||||
dst += 2;
|
||||
src += 2;
|
||||
|
@ -273,7 +276,7 @@ bmcr_full_transparency:
|
|||
if (src->a == 0) break;
|
||||
if (src_mv->m) {
|
||||
const uint r = remap[src_mv->m];
|
||||
*anim = (animated && src->a == 255) ? r | ((uint16_t) src_mv->v << 8 ) : 0;
|
||||
*anim = (animated && src->a == 255) ? r | ((uint16_t)src_mv->v << 8) : 0;
|
||||
if (r != 0) {
|
||||
Colour remapped_colour = AdjustBrightneSSE(this->LookupColourInPalette(r), src_mv->v);
|
||||
if (src->a == 255) {
|
||||
|
@ -288,7 +291,7 @@ bmcr_full_transparency:
|
|||
*anim = 0;
|
||||
srcABCD = _mm_cvtsi32_si128(src->data);
|
||||
if (src->a < 255) {
|
||||
bmcr_alpha_blend_single:
|
||||
bmcr_alpha_blend_single:
|
||||
__m128i dstABCD = _mm_cvtsi32_si128(dst->data);
|
||||
srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm, a_am);
|
||||
}
|
||||
|
@ -299,10 +302,10 @@ bmcr_alpha_blend_single:
|
|||
|
||||
case BlitterMode::Transparent:
|
||||
/* Make the current colour a bit more black, so it looks like this image is transparent. */
|
||||
for (uint x = (uint) bp->width / 2; x > 0; x--) {
|
||||
__m128i srcABCD = _mm_loadl_epi64((const __m128i*) src);
|
||||
__m128i dstABCD = _mm_loadl_epi64((__m128i*) dst);
|
||||
_mm_storel_epi64((__m128i *) dst, DarkenTwoPixels(srcABCD, dstABCD, a_cm, tr_nom_base));
|
||||
for (uint x = (uint)bp->width / 2; x > 0; x--) {
|
||||
__m128i srcABCD = _mm_loadl_epi64((const __m128i *)src);
|
||||
__m128i dstABCD = _mm_loadl_epi64((__m128i *)dst);
|
||||
_mm_storel_epi64((__m128i *)dst, DarkenTwoPixels(srcABCD, dstABCD, a_cm, tr_nom_base));
|
||||
src += 2;
|
||||
dst += 2;
|
||||
anim += 2;
|
||||
|
@ -320,7 +323,7 @@ bmcr_alpha_blend_single:
|
|||
|
||||
case BlitterMode::TransparentRemap:
|
||||
/* Apply custom transparency remap. */
|
||||
for (uint x = (uint) bp->width; x > 0; x--) {
|
||||
for (uint x = (uint)bp->width; x > 0; x--) {
|
||||
if (src->a != 0) {
|
||||
*dst = this->LookupColourInPalette(remap[GetNearestColourIndex(*dst)]);
|
||||
*anim = 0;
|
||||
|
@ -332,9 +335,8 @@ bmcr_alpha_blend_single:
|
|||
}
|
||||
break;
|
||||
|
||||
|
||||
case BlitterMode::CrashRemap:
|
||||
for (uint x = (uint) bp->width; x > 0; x--) {
|
||||
for (uint x = (uint)bp->width; x > 0; x--) {
|
||||
if (src_mv->m == 0) {
|
||||
if (src->a != 0) {
|
||||
uint8_t g = MakeDark(src->r, src->g, src->b);
|
||||
|
@ -353,7 +355,7 @@ bmcr_alpha_blend_single:
|
|||
break;
|
||||
|
||||
case BlitterMode::BlackRemap:
|
||||
for (uint x = (uint) bp->width; x > 0; x--) {
|
||||
for (uint x = (uint)bp->width; x > 0; x--) {
|
||||
if (src->a != 0) {
|
||||
*dst = Colour(0, 0, 0);
|
||||
*anim = 0;
|
||||
|
@ -366,13 +368,14 @@ bmcr_alpha_blend_single:
|
|||
break;
|
||||
}
|
||||
|
||||
next_line:
|
||||
next_line:
|
||||
if (mode != BlitterMode::Transparent && mode != BlitterMode::TransparentRemap) src_mv_line += si->sprite_width;
|
||||
src_rgba_line = (const Colour*) ((const uint8_t*) src_rgba_line + si->sprite_line_size);
|
||||
src_rgba_line = (const Colour *)((const uint8_t *)src_rgba_line + si->sprite_line_size);
|
||||
dst_line += bp->pitch;
|
||||
anim_line += this->anim_buf_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
IGNORE_UNINITIALIZED_WARNING_STOP
|
||||
|
||||
/**
|
||||
|
@ -390,49 +393,71 @@ void Blitter_32bppSSE4_Anim::Draw(Blitter::BlitterParams *bp, BlitterMode mode,
|
|||
return;
|
||||
}
|
||||
|
||||
const Blitter_32bppSSE_Base::SpriteFlags sprite_flags = ((const Blitter_32bppSSE_Base::SpriteData *) bp->sprite)->flags;
|
||||
const Blitter_32bppSSE_Base::SpriteFlags sprite_flags = ((const Blitter_32bppSSE_Base::SpriteData *)bp->sprite)->flags;
|
||||
switch (mode) {
|
||||
default: {
|
||||
bm_normal:
|
||||
bm_normal:
|
||||
if (bp->skip_left != 0 || bp->width <= MARGIN_NORMAL_THRESHOLD) {
|
||||
const BlockType bt_last = (BlockType) (bp->width & 1);
|
||||
const BlockType bt_last = (BlockType)(bp->width & 1);
|
||||
if (bt_last == BT_EVEN) {
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true, false>(bp, zoom);
|
||||
else Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true, true>(bp, zoom);
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim))
|
||||
Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true, false>(bp, zoom);
|
||||
else
|
||||
Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true, true>(bp, zoom);
|
||||
} else {
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true, false>(bp, zoom);
|
||||
else Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true, true>(bp, zoom);
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim))
|
||||
Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true, false>(bp, zoom);
|
||||
else
|
||||
Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true, true>(bp, zoom);
|
||||
}
|
||||
} else {
|
||||
#ifdef POINTER_IS_64BIT
|
||||
# ifdef POINTER_IS_64BIT
|
||||
if (sprite_flags.Test(SpriteFlag::Translucent)) {
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
|
||||
else Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim))
|
||||
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
|
||||
else
|
||||
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
|
||||
} else {
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false, false>(bp, zoom);
|
||||
else Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false, true>(bp, zoom);
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim))
|
||||
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false, false>(bp, zoom);
|
||||
else
|
||||
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false, true>(bp, zoom);
|
||||
}
|
||||
#else
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
|
||||
else Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
|
||||
#endif
|
||||
# else
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim))
|
||||
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
|
||||
else
|
||||
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
|
||||
# endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BlitterMode::ColourRemap:
|
||||
if (sprite_flags.Test(SpriteFlag::NoRemap)) goto bm_normal;
|
||||
if (bp->skip_left != 0 || bp->width <= MARGIN_REMAP_THRESHOLD) {
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true, false>(bp, zoom);
|
||||
else Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true, true>(bp, zoom);
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim))
|
||||
Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true, false>(bp, zoom);
|
||||
else
|
||||
Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true, true>(bp, zoom);
|
||||
} else {
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
|
||||
else Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
|
||||
if (sprite_flags.Test(SpriteFlag::NoAnim))
|
||||
Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
|
||||
else
|
||||
Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
|
||||
}
|
||||
break;
|
||||
case BlitterMode::Transparent: Draw<BlitterMode::Transparent, RM_NONE, BT_NONE, true, true>(bp, zoom); return;
|
||||
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap, RM_NONE, BT_NONE, true, true>(bp, zoom); return;
|
||||
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap, RM_NONE, BT_NONE, true, true>(bp, zoom); return;
|
||||
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap, RM_NONE, BT_NONE, true, true>(bp, zoom); return;
|
||||
case BlitterMode::Transparent:
|
||||
Draw<BlitterMode::Transparent, RM_NONE, BT_NONE, true, true>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::TransparentRemap:
|
||||
Draw<BlitterMode::TransparentRemap, RM_NONE, BT_NONE, true, true>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::CrashRemap:
|
||||
Draw<BlitterMode::CrashRemap, RM_NONE, BT_NONE, true, true>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::BlackRemap:
|
||||
Draw<BlitterMode::BlackRemap, RM_NONE, BT_NONE, true, true>(bp, zoom);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,45 +12,55 @@
|
|||
|
||||
#ifdef WITH_SSE
|
||||
|
||||
#ifndef SSE_VERSION
|
||||
#define SSE_VERSION 4
|
||||
#endif
|
||||
# ifndef SSE_VERSION
|
||||
# define SSE_VERSION 4
|
||||
# endif
|
||||
|
||||
#ifndef SSE_TARGET
|
||||
#define SSE_TARGET "sse4.1"
|
||||
#endif
|
||||
# ifndef SSE_TARGET
|
||||
# define SSE_TARGET "sse4.1"
|
||||
# endif
|
||||
|
||||
#ifndef FULL_ANIMATION
|
||||
#define FULL_ANIMATION 1
|
||||
#endif
|
||||
# ifndef FULL_ANIMATION
|
||||
# define FULL_ANIMATION 1
|
||||
# endif
|
||||
|
||||
#include "32bpp_anim.hpp"
|
||||
#include "32bpp_anim_sse2.hpp"
|
||||
#include "32bpp_sse4.hpp"
|
||||
# include "32bpp_anim.hpp"
|
||||
# include "32bpp_anim_sse2.hpp"
|
||||
# include "32bpp_sse4.hpp"
|
||||
|
||||
#undef MARGIN_NORMAL_THRESHOLD
|
||||
#define MARGIN_NORMAL_THRESHOLD 4
|
||||
# undef MARGIN_NORMAL_THRESHOLD
|
||||
# define MARGIN_NORMAL_THRESHOLD 4
|
||||
|
||||
/** The SSE4 32 bpp blitter with palette animation. */
|
||||
class Blitter_32bppSSE4_Anim final : public Blitter_32bppSSE2_Anim, public Blitter_32bppSSE4 {
|
||||
private:
|
||||
|
||||
public:
|
||||
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent, bool animated>
|
||||
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
||||
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override {
|
||||
|
||||
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override
|
||||
{
|
||||
return Blitter_32bppSSE_Base::Encode(sprite, allocator);
|
||||
}
|
||||
std::string_view GetName() override { return "32bpp-sse4-anim"; }
|
||||
|
||||
std::string_view GetName() override
|
||||
{
|
||||
return "32bpp-sse4-anim";
|
||||
}
|
||||
|
||||
using Blitter_32bppSSE2_Anim::LookupColourInPalette;
|
||||
};
|
||||
|
||||
/** Factory for the SSE4 32 bpp blitter (with palette animation). */
|
||||
class FBlitter_32bppSSE4_Anim: public BlitterFactory {
|
||||
class FBlitter_32bppSSE4_Anim : public BlitterFactory {
|
||||
public:
|
||||
FBlitter_32bppSSE4_Anim() : BlitterFactory("32bpp-sse4-anim", "32bpp SSE4 Blitter (palette animation)", HasCPUIDFlag(1, 2, 19)) {}
|
||||
std::unique_ptr<Blitter> CreateInstance() override { return std::unique_ptr<Blitter>(static_cast<Blitter_32bppSSE2_Anim *>(new Blitter_32bppSSE4_Anim())); }
|
||||
|
||||
std::unique_ptr<Blitter> CreateInstance() override
|
||||
{
|
||||
return std::unique_ptr<Blitter>(static_cast<Blitter_32bppSSE2_Anim *>(new Blitter_32bppSSE4_Anim()));
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* WITH_SSE */
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
/** @file 32bpp_base.cpp Implementation of base for 32 bpp blitters. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "32bpp_base.hpp"
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
|
|
@ -10,14 +10,18 @@
|
|||
#ifndef BLITTER_32BPP_BASE_HPP
|
||||
#define BLITTER_32BPP_BASE_HPP
|
||||
|
||||
#include "base.hpp"
|
||||
#include "../gfx_func.h"
|
||||
#include "../palette_func.h"
|
||||
#include "base.hpp"
|
||||
|
||||
/** Base for all 32bpp blitters. */
|
||||
class Blitter_32bppBase : public Blitter {
|
||||
public:
|
||||
uint8_t GetScreenDepth() override { return 32; }
|
||||
uint8_t GetScreenDepth() override
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
void *MoveTo(void *video, int x, int y) override;
|
||||
void SetPixel(void *video, int x, int y, uint8_t colour) override;
|
||||
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) override;
|
||||
|
@ -48,10 +52,7 @@ public:
|
|||
uint cb = current.b;
|
||||
|
||||
/* The 256 is wrong, it should be 255, but 256 is much faster... */
|
||||
return Colour(
|
||||
((int)(r - cr) * a) / 256 + cr,
|
||||
((int)(g - cg) * a) / 256 + cg,
|
||||
((int)(b - cb) * a) / 256 + cb);
|
||||
return Colour(((int)(r - cr) * a) / 256 + cr, ((int)(g - cg) * a) / 256 + cg, ((int)(b - cb) * a) / 256 + cb);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,9 +72,9 @@ public:
|
|||
*/
|
||||
static inline Colour ComposeColourPANoCheck(Colour colour, uint a, Colour current)
|
||||
{
|
||||
uint r = colour.r;
|
||||
uint g = colour.g;
|
||||
uint b = colour.b;
|
||||
uint r = colour.r;
|
||||
uint g = colour.g;
|
||||
uint b = colour.b;
|
||||
|
||||
return ComposeColourRGBANoCheck(r, g, b, a, current);
|
||||
}
|
||||
|
|
|
@ -8,11 +8,13 @@
|
|||
/** @file 32bpp_optimized.cpp Implementation of the optimized 32 bpp blitter. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../zoom_func.h"
|
||||
#include "../settings_type.h"
|
||||
#include "../palette_func.h"
|
||||
|
||||
#include "32bpp_optimized.hpp"
|
||||
|
||||
#include "../palette_func.h"
|
||||
#include "../settings_type.h"
|
||||
#include "../zoom_func.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/** Instantiation of the optimized 32bpp blitter factory. */
|
||||
|
@ -36,7 +38,7 @@ inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomL
|
|||
/* src_n : each line begins with uint32_t n = 'number of bytes in this line',
|
||||
* then interleaved stream of 'm' and 'n' channels. 'm' is remap,
|
||||
* 'n' is number of bytes with the same alpha channel class */
|
||||
const uint16_t *src_n = (const uint16_t *)(src->data + src->offset[zoom][1]);
|
||||
const uint16_t *src_n = (const uint16_t *)(src->data + src->offset[zoom][1]);
|
||||
|
||||
/* skip upper lines in src_px and src_n */
|
||||
for (uint i = bp->skip_top; i != 0; i--) {
|
||||
|
@ -73,7 +75,7 @@ inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomL
|
|||
|
||||
if (src_px->a == 0) {
|
||||
dst += n;
|
||||
src_px ++;
|
||||
src_px++;
|
||||
src_n++;
|
||||
} else {
|
||||
if (dst + n > dst_end) {
|
||||
|
@ -108,7 +110,7 @@ inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomL
|
|||
continue;
|
||||
}
|
||||
|
||||
draw:;
|
||||
draw:;
|
||||
|
||||
switch (mode) {
|
||||
case BlitterMode::ColourRemap:
|
||||
|
@ -252,7 +254,7 @@ inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomL
|
|||
|
||||
dst = dst_ln;
|
||||
src_px = src_px_ln;
|
||||
src_n = src_n_ln;
|
||||
src_n = src_n_ln;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,13 +262,26 @@ template <bool Tpal_to_rgb>
|
|||
void Blitter_32bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
||||
{
|
||||
switch (mode) {
|
||||
default: NOT_REACHED();
|
||||
case BlitterMode::Normal: Draw<BlitterMode::Normal, Tpal_to_rgb>(bp, zoom); return;
|
||||
case BlitterMode::ColourRemap: Draw<BlitterMode::ColourRemap, Tpal_to_rgb>(bp, zoom); return;
|
||||
case BlitterMode::Transparent: Draw<BlitterMode::Transparent, Tpal_to_rgb>(bp, zoom); return;
|
||||
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap, Tpal_to_rgb>(bp, zoom); return;
|
||||
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap, Tpal_to_rgb>(bp, zoom); return;
|
||||
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap, Tpal_to_rgb>(bp, zoom); return;
|
||||
default:
|
||||
NOT_REACHED();
|
||||
case BlitterMode::Normal:
|
||||
Draw<BlitterMode::Normal, Tpal_to_rgb>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::ColourRemap:
|
||||
Draw<BlitterMode::ColourRemap, Tpal_to_rgb>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::Transparent:
|
||||
Draw<BlitterMode::Transparent, Tpal_to_rgb>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::TransparentRemap:
|
||||
Draw<BlitterMode::TransparentRemap, Tpal_to_rgb>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::CrashRemap:
|
||||
Draw<BlitterMode::CrashRemap, Tpal_to_rgb>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::BlackRemap:
|
||||
Draw<BlitterMode::BlackRemap, Tpal_to_rgb>(bp, zoom);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,7 +300,8 @@ void Blitter_32bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode,
|
|||
this->Draw<false>(bp, mode, zoom);
|
||||
}
|
||||
|
||||
template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
||||
template <bool Tpal_to_rgb>
|
||||
Sprite *Blitter_32bppOptimized::EncodeInternal(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
||||
{
|
||||
/* streams of pixels (a, r, g, b channels)
|
||||
*
|
||||
|
@ -321,10 +337,10 @@ template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const
|
|||
uint size = src_orig->height * src_orig->width;
|
||||
|
||||
dst_px_orig[z] = std::make_unique<Colour[]>(size + src_orig->height * 2);
|
||||
dst_n_orig[z] = std::make_unique<uint16_t[]>(size * 2 + src_orig->height * 4 * 2);
|
||||
dst_n_orig[z] = std::make_unique<uint16_t[]>(size * 2 + src_orig->height * 4 * 2);
|
||||
|
||||
uint32_t *dst_px_ln = reinterpret_cast<uint32_t *>(dst_px_orig[z].get());
|
||||
uint32_t *dst_n_ln = reinterpret_cast<uint32_t *>(dst_n_orig[z].get());
|
||||
uint32_t *dst_n_ln = reinterpret_cast<uint32_t *>(dst_n_orig[z].get());
|
||||
|
||||
const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *)src_orig->data;
|
||||
|
||||
|
@ -358,7 +374,7 @@ template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const
|
|||
*dst_n = src->m;
|
||||
if (src->m != 0) {
|
||||
/* Get brightest value */
|
||||
uint8_t rgb_max = std::max({ src->r, src->g, src->b });
|
||||
uint8_t rgb_max = std::max({src->r, src->g, src->b});
|
||||
|
||||
/* Black pixel (8bpp or old 32bpp image), so use default value */
|
||||
if (rgb_max == 0) rgb_max = DEFAULT_BRIGHTNESS;
|
||||
|
@ -396,17 +412,17 @@ template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const
|
|||
}
|
||||
|
||||
dst_px = (Colour *)AlignPtr(dst_px, 4);
|
||||
dst_n = (uint16_t *)AlignPtr(dst_n, 4);
|
||||
dst_n = (uint16_t *)AlignPtr(dst_n, 4);
|
||||
|
||||
*dst_px_ln = (uint8_t *)dst_px - (uint8_t *)dst_px_ln;
|
||||
*dst_n_ln = (uint8_t *)dst_n - (uint8_t *)dst_n_ln;
|
||||
*dst_n_ln = (uint8_t *)dst_n - (uint8_t *)dst_n_ln;
|
||||
|
||||
dst_px_ln = (uint32_t *)dst_px;
|
||||
dst_n_ln = (uint32_t *)dst_n;
|
||||
dst_n_ln = (uint32_t *)dst_n;
|
||||
}
|
||||
|
||||
lengths[z][0] = reinterpret_cast<uint8_t *>(dst_px_ln) - reinterpret_cast<uint8_t *>(dst_px_orig[z].get()); // all are aligned to 4B boundary
|
||||
lengths[z][1] = reinterpret_cast<uint8_t *>(dst_n_ln) - reinterpret_cast<uint8_t *>(dst_n_orig[z].get());
|
||||
lengths[z][1] = reinterpret_cast<uint8_t *>(dst_n_ln) - reinterpret_cast<uint8_t *>(dst_n_orig[z].get());
|
||||
}
|
||||
|
||||
uint len = 0; // total length of data
|
||||
|
@ -417,7 +433,7 @@ template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const
|
|||
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + sizeof(SpriteData) + len);
|
||||
|
||||
dest_sprite->height = sprite[ZOOM_LVL_MIN].height;
|
||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
||||
dest_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
|
||||
dest_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
|
||||
|
||||
|
@ -429,7 +445,7 @@ template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const
|
|||
dst->offset[z][1] = lengths[z][0] + dst->offset[z][0];
|
||||
|
||||
memcpy(dst->data + dst->offset[z][0], dst_px_orig[z].get(), lengths[z][0]);
|
||||
memcpy(dst->data + dst->offset[z][1], dst_n_orig[z].get(), lengths[z][1]);
|
||||
memcpy(dst->data + dst->offset[z][1], dst_n_orig[z].get(), lengths[z][1]);
|
||||
}
|
||||
|
||||
return dest_sprite;
|
||||
|
|
|
@ -18,26 +18,36 @@ public:
|
|||
/** Data stored about a (single) sprite. */
|
||||
struct SpriteData {
|
||||
uint32_t offset[ZOOM_LVL_END][2]; ///< Offsets (from .data) to streams for different zoom levels, and the normal and remap image information.
|
||||
uint8_t data[]; ///< Data, all zoomlevels.
|
||||
uint8_t data[]; ///< Data, all zoomlevels.
|
||||
};
|
||||
|
||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
||||
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
|
||||
|
||||
std::string_view GetName() override { return "32bpp-optimized"; }
|
||||
std::string_view GetName() override
|
||||
{
|
||||
return "32bpp-optimized";
|
||||
}
|
||||
|
||||
template <BlitterMode mode, bool Tpal_to_rgb = false> void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
||||
template <BlitterMode mode, bool Tpal_to_rgb = false>
|
||||
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
||||
|
||||
protected:
|
||||
template <bool Tpal_to_rgb> void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
|
||||
template <bool Tpal_to_rgb> Sprite *EncodeInternal(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
|
||||
template <bool Tpal_to_rgb>
|
||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
|
||||
template <bool Tpal_to_rgb>
|
||||
Sprite *EncodeInternal(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
|
||||
};
|
||||
|
||||
/** Factory for the optimised 32 bpp blitter (without palette animation). */
|
||||
class FBlitter_32bppOptimized : public BlitterFactory {
|
||||
public:
|
||||
FBlitter_32bppOptimized() : BlitterFactory("32bpp-optimized", "32bpp Optimized Blitter (no palette animation)") {}
|
||||
std::unique_ptr<Blitter> CreateInstance() override { return std::make_unique<Blitter_32bppOptimized>(); }
|
||||
|
||||
std::unique_ptr<Blitter> CreateInstance() override
|
||||
{
|
||||
return std::make_unique<Blitter_32bppOptimized>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* BLITTER_32BPP_OPTIMIZED_HPP */
|
||||
|
|
|
@ -8,10 +8,12 @@
|
|||
/** @file 32bpp_simple.cpp Implementation of the simple 32 bpp blitter. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../zoom_func.h"
|
||||
#include "../palette_func.h"
|
||||
|
||||
#include "32bpp_simple.hpp"
|
||||
|
||||
#include "../palette_func.h"
|
||||
#include "../zoom_func.h"
|
||||
|
||||
#include "../table/sprites.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
@ -121,7 +123,7 @@ Sprite *Blitter_32bppSimple::Encode(const SpriteLoader::SpriteCollection &sprite
|
|||
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + static_cast<size_t>(sprite[ZOOM_LVL_MIN].height) * static_cast<size_t>(sprite[ZOOM_LVL_MIN].width) * sizeof(*dst));
|
||||
|
||||
dest_sprite->height = sprite[ZOOM_LVL_MIN].height;
|
||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
||||
dest_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
|
||||
dest_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
|
||||
|
||||
|
|
|
@ -16,26 +16,34 @@
|
|||
/** The most trivial 32 bpp blitter (without palette animation). */
|
||||
class Blitter_32bppSimple : public Blitter_32bppBase {
|
||||
struct Pixel {
|
||||
uint8_t r; ///< Red-channel
|
||||
uint8_t g; ///< Green-channel
|
||||
uint8_t b; ///< Blue-channel
|
||||
uint8_t a; ///< Alpha-channel
|
||||
uint8_t m; ///< Remap-channel
|
||||
uint8_t v; ///< Brightness-channel
|
||||
uint8_t r; ///< Red-channel
|
||||
uint8_t g; ///< Green-channel
|
||||
uint8_t b; ///< Blue-channel
|
||||
uint8_t a; ///< Alpha-channel
|
||||
uint8_t m; ///< Remap-channel
|
||||
uint8_t v; ///< Brightness-channel
|
||||
};
|
||||
|
||||
public:
|
||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
||||
void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override;
|
||||
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
|
||||
|
||||
std::string_view GetName() override { return "32bpp-simple"; }
|
||||
std::string_view GetName() override
|
||||
{
|
||||
return "32bpp-simple";
|
||||
}
|
||||
};
|
||||
|
||||
/** Factory for the simple 32 bpp blitter. */
|
||||
class FBlitter_32bppSimple : public BlitterFactory {
|
||||
public:
|
||||
FBlitter_32bppSimple() : BlitterFactory("32bpp-simple", "32bpp Simple Blitter (no palette animation)") {}
|
||||
std::unique_ptr<Blitter> CreateInstance() override { return std::make_unique<Blitter_32bppSimple>(); }
|
||||
|
||||
std::unique_ptr<Blitter> CreateInstance() override
|
||||
{
|
||||
return std::make_unique<Blitter_32bppSimple>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* BLITTER_32BPP_SIMPLE_HPP */
|
||||
|
|
|
@ -9,13 +9,15 @@
|
|||
|
||||
#ifdef WITH_SSE
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../zoom_func.h"
|
||||
#include "../settings_type.h"
|
||||
#include "32bpp_sse2.hpp"
|
||||
#include "32bpp_sse_func.hpp"
|
||||
# include "../stdafx.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
# include "32bpp_sse2.hpp"
|
||||
|
||||
# include "../settings_type.h"
|
||||
# include "../zoom_func.h"
|
||||
# include "32bpp_sse_func.hpp"
|
||||
|
||||
# include "../safeguards.h"
|
||||
|
||||
/** Instantiation of the SSE2 32bpp blitter factory. */
|
||||
static FBlitter_32bppSSE2 iFBlitter_32bppSSE2;
|
||||
|
@ -52,7 +54,7 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &spri
|
|||
|
||||
Sprite *dst_sprite = allocator.Allocate<Sprite>(sizeof(Sprite) + sizeof(SpriteData) + all_sprites_size);
|
||||
dst_sprite->height = sprite[ZOOM_LVL_MIN].height;
|
||||
dst_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
||||
dst_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
||||
dst_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
|
||||
dst_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
|
||||
memcpy(dst_sprite->data, &sd, sizeof(SpriteData));
|
||||
|
@ -63,9 +65,9 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &spri
|
|||
bool has_translucency = false;
|
||||
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
|
||||
const SpriteLoader::Sprite *src_sprite = &sprite[z];
|
||||
const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *) src_sprite->data;
|
||||
Colour *dst_rgba_line = (Colour *) &dst_sprite->data[sizeof(SpriteData) + sd.infos[z].sprite_offset];
|
||||
MapValue *dst_mv = (MapValue *) &dst_sprite->data[sizeof(SpriteData) + sd.infos[z].mv_offset];
|
||||
const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *)src_sprite->data;
|
||||
Colour *dst_rgba_line = (Colour *)&dst_sprite->data[sizeof(SpriteData) + sd.infos[z].sprite_offset];
|
||||
MapValue *dst_mv = (MapValue *)&dst_sprite->data[sizeof(SpriteData) + sd.infos[z].mv_offset];
|
||||
for (uint y = src_sprite->height; y != 0; y--) {
|
||||
Colour *dst_rgba = dst_rgba_line + META_LENGTH;
|
||||
for (uint x = src_sprite->width; x != 0; x--) {
|
||||
|
@ -95,7 +97,7 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &spri
|
|||
}
|
||||
} else {
|
||||
dst_rgba->data = 0;
|
||||
*(uint16_t*) dst_mv = 0;
|
||||
*(uint16_t *)dst_mv = 0;
|
||||
}
|
||||
dst_rgba++;
|
||||
dst_mv++;
|
||||
|
@ -106,21 +108,25 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &spri
|
|||
dst_rgba = dst_rgba_line + META_LENGTH;
|
||||
uint32_t nb_pix_transp = 0;
|
||||
for (uint x = src_sprite->width; x != 0; x--) {
|
||||
if (dst_rgba->a == 0) nb_pix_transp++;
|
||||
else break;
|
||||
if (dst_rgba->a == 0)
|
||||
nb_pix_transp++;
|
||||
else
|
||||
break;
|
||||
dst_rgba++;
|
||||
}
|
||||
(*dst_rgba_line).data = nb_pix_transp;
|
||||
|
||||
Colour *nb_right = dst_rgba_line + 1;
|
||||
dst_rgba_line = (Colour*) ((uint8_t*) dst_rgba_line + sd.infos[z].sprite_line_size);
|
||||
dst_rgba_line = (Colour *)((uint8_t *)dst_rgba_line + sd.infos[z].sprite_line_size);
|
||||
|
||||
/* Count the number of transparent pixels from the right. */
|
||||
dst_rgba = dst_rgba_line - 1;
|
||||
nb_pix_transp = 0;
|
||||
for (uint x = src_sprite->width; x != 0; x--) {
|
||||
if (dst_rgba->a == 0) nb_pix_transp++;
|
||||
else break;
|
||||
if (dst_rgba->a == 0)
|
||||
nb_pix_transp++;
|
||||
else
|
||||
break;
|
||||
dst_rgba--;
|
||||
}
|
||||
(*nb_right).data = nb_pix_transp;
|
||||
|
|
|
@ -12,19 +12,19 @@
|
|||
|
||||
#ifdef WITH_SSE
|
||||
|
||||
#ifndef SSE_VERSION
|
||||
#define SSE_VERSION 2
|
||||
#endif
|
||||
# ifndef SSE_VERSION
|
||||
# define SSE_VERSION 2
|
||||
# endif
|
||||
|
||||
#ifndef SSE_TARGET
|
||||
#define SSE_TARGET "sse2"
|
||||
#endif
|
||||
# ifndef SSE_TARGET
|
||||
# define SSE_TARGET "sse2"
|
||||
# endif
|
||||
|
||||
#ifndef FULL_ANIMATION
|
||||
#define FULL_ANIMATION 0
|
||||
#endif
|
||||
# ifndef FULL_ANIMATION
|
||||
# define FULL_ANIMATION 0
|
||||
# endif
|
||||
|
||||
#include "32bpp_sse_type.h"
|
||||
# include "32bpp_sse_type.h"
|
||||
|
||||
/** Base methods for 32bpp SSE blitters. */
|
||||
class Blitter_32bppSSE_Base {
|
||||
|
@ -35,19 +35,20 @@ public:
|
|||
uint8_t m;
|
||||
uint8_t v;
|
||||
};
|
||||
|
||||
static_assert(sizeof(MapValue) == 2);
|
||||
|
||||
/** Helper for creating specialised functions for specific optimisations. */
|
||||
enum ReadMode : uint8_t {
|
||||
RM_WITH_SKIP, ///< Use normal code for skipping empty pixels.
|
||||
RM_WITH_SKIP, ///< Use normal code for skipping empty pixels.
|
||||
RM_WITH_MARGIN, ///< Use cached number of empty pixels at begin and end of line to reduce work.
|
||||
RM_NONE, ///< No specialisation.
|
||||
RM_NONE, ///< No specialisation.
|
||||
};
|
||||
|
||||
/** Helper for creating specialised functions for the case where the sprite width is odd or even. */
|
||||
enum BlockType : uint8_t {
|
||||
BT_EVEN, ///< An even number of pixels in the width; no need for a special case for the last pixel.
|
||||
BT_ODD, ///< An odd number of pixels in the width; special case for the last pixel.
|
||||
BT_ODD, ///< An odd number of pixels in the width; special case for the last pixel.
|
||||
BT_NONE, ///< No specialisation for either case.
|
||||
};
|
||||
|
||||
|
@ -66,11 +67,12 @@ public:
|
|||
|
||||
/** Data stored about a (single) sprite. */
|
||||
struct SpriteInfo {
|
||||
uint32_t sprite_offset = 0; ///< The offset to the sprite data.
|
||||
uint32_t mv_offset = 0; ///< The offset to the map value data.
|
||||
uint32_t sprite_offset = 0; ///< The offset to the sprite data.
|
||||
uint32_t mv_offset = 0; ///< The offset to the map value data.
|
||||
uint16_t sprite_line_size = 0; ///< The size of a single line (pitch).
|
||||
uint16_t sprite_width = 0; ///< The width of the sprite.
|
||||
uint16_t sprite_width = 0; ///< The width of the sprite.
|
||||
};
|
||||
|
||||
struct SpriteData {
|
||||
SpriteFlags flags{};
|
||||
std::array<SpriteInfo, ZOOM_LVL_END> infos{};
|
||||
|
@ -87,18 +89,26 @@ public:
|
|||
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent>
|
||||
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
||||
|
||||
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override {
|
||||
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override
|
||||
{
|
||||
return Blitter_32bppSSE_Base::Encode(sprite, allocator);
|
||||
}
|
||||
|
||||
std::string_view GetName() override { return "32bpp-sse2"; }
|
||||
std::string_view GetName() override
|
||||
{
|
||||
return "32bpp-sse2";
|
||||
}
|
||||
};
|
||||
|
||||
/** Factory for the SSE2 32 bpp blitter (without palette animation). */
|
||||
class FBlitter_32bppSSE2 : public BlitterFactory {
|
||||
public:
|
||||
FBlitter_32bppSSE2() : BlitterFactory("32bpp-sse2", "32bpp SSE2 Blitter (no palette animation)", HasCPUIDFlag(1, 3, 26)) {}
|
||||
std::unique_ptr<Blitter> CreateInstance() override { return std::make_unique<Blitter_32bppSSE2>(); }
|
||||
|
||||
std::unique_ptr<Blitter> CreateInstance() override
|
||||
{
|
||||
return std::make_unique<Blitter_32bppSSE2>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* WITH_SSE */
|
||||
|
|
|
@ -9,13 +9,15 @@
|
|||
|
||||
#ifdef WITH_SSE
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../zoom_func.h"
|
||||
#include "../settings_type.h"
|
||||
#include "32bpp_sse4.hpp"
|
||||
#include "32bpp_sse_func.hpp"
|
||||
# include "../stdafx.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
# include "32bpp_sse4.hpp"
|
||||
|
||||
# include "../settings_type.h"
|
||||
# include "../zoom_func.h"
|
||||
# include "32bpp_sse_func.hpp"
|
||||
|
||||
# include "../safeguards.h"
|
||||
|
||||
/** Instantiation of the SSE4 32bpp blitter factory. */
|
||||
static FBlitter_32bppSSE4 iFBlitter_32bppSSE4;
|
||||
|
|
|
@ -12,19 +12,19 @@
|
|||
|
||||
#ifdef WITH_SSE
|
||||
|
||||
#ifndef SSE_VERSION
|
||||
#define SSE_VERSION 4
|
||||
#endif
|
||||
# ifndef SSE_VERSION
|
||||
# define SSE_VERSION 4
|
||||
# endif
|
||||
|
||||
#ifndef SSE_TARGET
|
||||
#define SSE_TARGET "sse4.1"
|
||||
#endif
|
||||
# ifndef SSE_TARGET
|
||||
# define SSE_TARGET "sse4.1"
|
||||
# endif
|
||||
|
||||
#ifndef FULL_ANIMATION
|
||||
#define FULL_ANIMATION 0
|
||||
#endif
|
||||
# ifndef FULL_ANIMATION
|
||||
# define FULL_ANIMATION 0
|
||||
# endif
|
||||
|
||||
#include "32bpp_ssse3.hpp"
|
||||
# include "32bpp_ssse3.hpp"
|
||||
|
||||
/** The SSE4 32 bpp blitter (without palette animation). */
|
||||
class Blitter_32bppSSE4 : public Blitter_32bppSSSE3 {
|
||||
|
@ -32,14 +32,22 @@ public:
|
|||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
||||
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent>
|
||||
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
||||
std::string_view GetName() override { return "32bpp-sse4"; }
|
||||
|
||||
std::string_view GetName() override
|
||||
{
|
||||
return "32bpp-sse4";
|
||||
}
|
||||
};
|
||||
|
||||
/** Factory for the SSE4 32 bpp blitter (without palette animation). */
|
||||
class FBlitter_32bppSSE4: public BlitterFactory {
|
||||
class FBlitter_32bppSSE4 : public BlitterFactory {
|
||||
public:
|
||||
FBlitter_32bppSSE4() : BlitterFactory("32bpp-sse4", "32bpp SSE4 Blitter (no palette animation)", HasCPUIDFlag(1, 2, 19)) {}
|
||||
std::unique_ptr<Blitter> CreateInstance() override { return std::make_unique<Blitter_32bppSSE4>(); }
|
||||
|
||||
std::unique_ptr<Blitter> CreateInstance() override
|
||||
{
|
||||
return std::make_unique<Blitter_32bppSSE4>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* WITH_SSE */
|
||||
|
|
|
@ -20,82 +20,88 @@
|
|||
#ifdef WITH_SSE
|
||||
|
||||
GNU_TARGET(SSE_TARGET)
|
||||
|
||||
INTERNAL_LINKAGE inline void InsertFirstUint32(const uint32_t value, __m128i &into)
|
||||
{
|
||||
#if (SSE_VERSION >= 4)
|
||||
# if (SSE_VERSION >= 4)
|
||||
into = _mm_insert_epi32(into, value, 0);
|
||||
#else
|
||||
# else
|
||||
into = _mm_insert_epi16(into, value, 0);
|
||||
into = _mm_insert_epi16(into, value >> 16, 1);
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
|
||||
GNU_TARGET(SSE_TARGET)
|
||||
|
||||
INTERNAL_LINKAGE inline void InsertSecondUint32(const uint32_t value, __m128i &into)
|
||||
{
|
||||
#if (SSE_VERSION >= 4)
|
||||
# if (SSE_VERSION >= 4)
|
||||
into = _mm_insert_epi32(into, value, 1);
|
||||
#else
|
||||
# else
|
||||
into = _mm_insert_epi16(into, value, 2);
|
||||
into = _mm_insert_epi16(into, value >> 16, 3);
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
|
||||
GNU_TARGET(SSE_TARGET)
|
||||
|
||||
INTERNAL_LINKAGE inline void LoadUint64(const uint64_t value, __m128i &into)
|
||||
{
|
||||
#ifdef POINTER_IS_64BIT
|
||||
# ifdef POINTER_IS_64BIT
|
||||
into = _mm_cvtsi64_si128(value);
|
||||
#else
|
||||
#if (SSE_VERSION >= 4)
|
||||
into = _mm_cvtsi32_si128(value);
|
||||
InsertSecondUint32(value >> 32, into);
|
||||
#else
|
||||
(*(um128i*) &into).m128i_u64[0] = value;
|
||||
#endif
|
||||
#endif
|
||||
# else
|
||||
# if (SSE_VERSION >= 4)
|
||||
into = _mm_cvtsi32_si128(value);
|
||||
InsertSecondUint32(value >> 32, into);
|
||||
# else
|
||||
(*(um128i *)&into).m128i_u64[0] = value;
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
|
||||
GNU_TARGET(SSE_TARGET)
|
||||
|
||||
INTERNAL_LINKAGE inline __m128i PackUnsaturated(__m128i from, const __m128i &mask)
|
||||
{
|
||||
#if (SSE_VERSION == 2)
|
||||
from = _mm_and_si128(from, mask); // PAND, wipe high bytes to keep low bytes when packing
|
||||
# if (SSE_VERSION == 2)
|
||||
from = _mm_and_si128(from, mask); // PAND, wipe high bytes to keep low bytes when packing
|
||||
return _mm_packus_epi16(from, from); // PACKUSWB, pack 2 colours (with saturation)
|
||||
#else
|
||||
# else
|
||||
return _mm_shuffle_epi8(from, mask);
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
|
||||
GNU_TARGET(SSE_TARGET)
|
||||
|
||||
INTERNAL_LINKAGE inline __m128i DistributeAlpha(const __m128i from, const __m128i &mask)
|
||||
{
|
||||
#if (SSE_VERSION == 2)
|
||||
# if (SSE_VERSION == 2)
|
||||
__m128i alphaAB = _mm_shufflelo_epi16(from, 0x3F); // PSHUFLW, put alpha1 in front of each rgb1
|
||||
alphaAB = _mm_shufflehi_epi16(alphaAB, 0x3F); // PSHUFHW, put alpha2 in front of each rgb2
|
||||
return _mm_andnot_si128(mask, alphaAB); // PANDN, set alpha fields to 0
|
||||
#else
|
||||
alphaAB = _mm_shufflehi_epi16(alphaAB, 0x3F); // PSHUFHW, put alpha2 in front of each rgb2
|
||||
return _mm_andnot_si128(mask, alphaAB); // PANDN, set alpha fields to 0
|
||||
# else
|
||||
return _mm_shuffle_epi8(from, mask);
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
|
||||
GNU_TARGET(SSE_TARGET)
|
||||
|
||||
INTERNAL_LINKAGE inline __m128i AlphaBlendTwoPixels(__m128i src, __m128i dst, const __m128i &distribution_mask, const __m128i &pack_mask, const __m128i &alpha_mask)
|
||||
{
|
||||
__m128i srcAB = _mm_unpacklo_epi8(src, _mm_setzero_si128()); // PUNPCKLBW, expand each uint8_t into uint16
|
||||
__m128i srcAB = _mm_unpacklo_epi8(src, _mm_setzero_si128()); // PUNPCKLBW, expand each uint8_t into uint16
|
||||
__m128i dstAB = _mm_unpacklo_epi8(dst, _mm_setzero_si128());
|
||||
|
||||
__m128i alphaMaskAB = _mm_cmpgt_epi16(srcAB, _mm_setzero_si128()); // PCMPGTW (alpha > 0) ? 0xFFFF : 0
|
||||
__m128i alphaAB = _mm_sub_epi16(srcAB, alphaMaskAB); // if (alpha > 0) a++;
|
||||
__m128i alphaAB = _mm_sub_epi16(srcAB, alphaMaskAB); // if (alpha > 0) a++;
|
||||
alphaAB = DistributeAlpha(alphaAB, distribution_mask);
|
||||
|
||||
srcAB = _mm_sub_epi16(srcAB, dstAB); // PSUBW, (r - Cr)
|
||||
srcAB = _mm_sub_epi16(srcAB, dstAB); // PSUBW, (r - Cr)
|
||||
srcAB = _mm_mullo_epi16(srcAB, alphaAB); // PMULLW, a*(r - Cr)
|
||||
srcAB = _mm_srli_epi16(srcAB, 8); // PSRLW, a*(r - Cr)/256
|
||||
srcAB = _mm_add_epi16(srcAB, dstAB); // PADDW, a*(r - Cr)/256 + Cr
|
||||
srcAB = _mm_srli_epi16(srcAB, 8); // PSRLW, a*(r - Cr)/256
|
||||
srcAB = _mm_add_epi16(srcAB, dstAB); // PADDW, a*(r - Cr)/256 + Cr
|
||||
|
||||
alphaMaskAB = _mm_and_si128(alphaMaskAB, alpha_mask); // PAND, set non alpha fields to 0
|
||||
srcAB = _mm_or_si128(srcAB, alphaMaskAB); // POR, set alpha fields to 0xFFFF is src alpha was > 0
|
||||
srcAB = _mm_or_si128(srcAB, alphaMaskAB); // POR, set alpha fields to 0xFFFF is src alpha was > 0
|
||||
|
||||
return PackUnsaturated(srcAB, pack_mask);
|
||||
}
|
||||
|
@ -104,6 +110,7 @@ INTERNAL_LINKAGE inline __m128i AlphaBlendTwoPixels(__m128i src, __m128i dst, co
|
|||
* rgb = rgb * ((256/4) * 4 - (alpha/4)) / ((256/4) * 4)
|
||||
*/
|
||||
GNU_TARGET(SSE_TARGET)
|
||||
|
||||
INTERNAL_LINKAGE inline __m128i DarkenTwoPixels(__m128i src, __m128i dst, const __m128i &distribution_mask, const __m128i &tr_nom_base)
|
||||
{
|
||||
__m128i srcAB = _mm_unpacklo_epi8(src, _mm_setzero_si128());
|
||||
|
@ -118,9 +125,10 @@ INTERNAL_LINKAGE inline __m128i DarkenTwoPixels(__m128i src, __m128i dst, const
|
|||
|
||||
IGNORE_UNINITIALIZED_WARNING_START
|
||||
GNU_TARGET(SSE_TARGET)
|
||||
|
||||
INTERNAL_LINKAGE Colour ReallyAdjustBrightness(Colour colour, uint8_t brightness)
|
||||
{
|
||||
uint64_t c16 = colour.b | (uint64_t) colour.g << 16 | (uint64_t) colour.r << 32;
|
||||
uint64_t c16 = colour.b | (uint64_t)colour.g << 16 | (uint64_t)colour.r << 32;
|
||||
c16 *= brightness;
|
||||
uint64_t c16_ob = c16; // Helps out of order execution.
|
||||
c16 /= DEFAULT_BRIGHTNESS;
|
||||
|
@ -128,7 +136,7 @@ INTERNAL_LINKAGE Colour ReallyAdjustBrightness(Colour colour, uint8_t brightness
|
|||
|
||||
/* Sum overbright (maximum for each rgb is 508, 9 bits, -255 is changed in -256 so we just have to take the 8 lower bits into account). */
|
||||
c16_ob = (((c16_ob >> (8 + 7)) & 0x0100010001ULL) * 0xFF) & c16;
|
||||
const uint ob = ((uint16_t) c16_ob + (uint16_t) (c16_ob >> 16) + (uint16_t) (c16_ob >> 32)) / 2;
|
||||
const uint ob = ((uint16_t)c16_ob + (uint16_t)(c16_ob >> 16) + (uint16_t)(c16_ob >> 32)) / 2;
|
||||
|
||||
const uint32_t alpha32 = colour.data & 0xFF000000;
|
||||
__m128i ret;
|
||||
|
@ -140,13 +148,14 @@ INTERNAL_LINKAGE Colour ReallyAdjustBrightness(Colour colour, uint8_t brightness
|
|||
__m128i c128 = ret;
|
||||
ret = _mm_subs_epu16(white, c128); // PSUBUSW, (255 - rgb)
|
||||
ret = _mm_mullo_epi16(ret, ob128); // PMULLW, ob*(255 - rgb)
|
||||
ret = _mm_srli_epi16(ret, 8); // PSRLW, ob*(255 - rgb)/256
|
||||
ret = _mm_add_epi16(ret, c128); // PADDW, ob*(255 - rgb)/256 + rgb
|
||||
ret = _mm_srli_epi16(ret, 8); // PSRLW, ob*(255 - rgb)/256
|
||||
ret = _mm_add_epi16(ret, c128); // PADDW, ob*(255 - rgb)/256 + rgb
|
||||
}
|
||||
|
||||
ret = _mm_packus_epi16(ret, ret); // PACKUSWB, saturate and pack.
|
||||
ret = _mm_packus_epi16(ret, ret); // PACKUSWB, saturate and pack.
|
||||
return alpha32 | _mm_cvtsi128_si32(ret);
|
||||
}
|
||||
|
||||
IGNORE_UNINITIALIZED_WARNING_STOP
|
||||
|
||||
/** ReallyAdjustBrightness() is not called that often.
|
||||
|
@ -161,11 +170,12 @@ INTERNAL_LINKAGE inline Colour AdjustBrightneSSE(Colour colour, uint8_t brightne
|
|||
}
|
||||
|
||||
GNU_TARGET(SSE_TARGET)
|
||||
|
||||
INTERNAL_LINKAGE inline __m128i AdjustBrightnessOfTwoPixels([[maybe_unused]] __m128i from, [[maybe_unused]] uint32_t brightness)
|
||||
{
|
||||
#if (SSE_VERSION < 3)
|
||||
# if (SSE_VERSION < 3)
|
||||
NOT_REACHED();
|
||||
#else
|
||||
# else
|
||||
/* The following dataflow differs from the one of AdjustBrightness() only for alpha.
|
||||
* In order to keep alpha in colAB, insert a 1 in a unused brightness byte (a*1->a).
|
||||
* OK, not a 1 but DEFAULT_BRIGHTNESS to compensate the div.
|
||||
|
@ -190,19 +200,19 @@ INTERNAL_LINKAGE inline __m128i AdjustBrightnessOfTwoPixels([[maybe_unused]] __m
|
|||
colAB_ob = _mm_and_si128(colAB_ob, colAB);
|
||||
__m128i obAB = _mm_hadd_epi16(_mm_hadd_epi16(colAB_ob, _mm_setzero_si128()), _mm_setzero_si128());
|
||||
|
||||
obAB = _mm_srli_epi16(obAB, 1); // Reduce overbright strength.
|
||||
obAB = _mm_srli_epi16(obAB, 1); // Reduce overbright strength.
|
||||
obAB = _mm_shuffle_epi8(obAB, OVERBRIGHT_CONTROL_MASK);
|
||||
__m128i retAB = OVERBRIGHT_VALUE_MASK; // ob_mask is equal to white.
|
||||
retAB = _mm_subs_epu16(retAB, colAB); // (255 - rgb)
|
||||
retAB = _mm_mullo_epi16(retAB, obAB); // ob*(255 - rgb)
|
||||
retAB = _mm_srli_epi16(retAB, 8); // ob*(255 - rgb)/256
|
||||
retAB = _mm_add_epi16(retAB, colAB); // ob*(255 - rgb)/256 + rgb
|
||||
retAB = _mm_subs_epu16(retAB, colAB); // (255 - rgb)
|
||||
retAB = _mm_mullo_epi16(retAB, obAB); // ob*(255 - rgb)
|
||||
retAB = _mm_srli_epi16(retAB, 8); // ob*(255 - rgb)/256
|
||||
retAB = _mm_add_epi16(retAB, colAB); // ob*(255 - rgb)/256 + rgb
|
||||
|
||||
return _mm_packus_epi16(retAB, retAB);
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
|
||||
#if FULL_ANIMATION == 0
|
||||
# if FULL_ANIMATION == 0
|
||||
/**
|
||||
* Draws a sprite to a (screen) buffer. It is templated to allow faster operation.
|
||||
*
|
||||
|
@ -213,23 +223,23 @@ INTERNAL_LINKAGE inline __m128i AdjustBrightnessOfTwoPixels([[maybe_unused]] __m
|
|||
IGNORE_UNINITIALIZED_WARNING_START
|
||||
template <BlitterMode mode, Blitter_32bppSSE2::ReadMode read_mode, Blitter_32bppSSE2::BlockType bt_last, bool translucent>
|
||||
GNU_TARGET(SSE_TARGET)
|
||||
#if (SSE_VERSION == 2)
|
||||
# if (SSE_VERSION == 2)
|
||||
inline void Blitter_32bppSSE2::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
|
||||
#elif (SSE_VERSION == 3)
|
||||
# elif (SSE_VERSION == 3)
|
||||
inline void Blitter_32bppSSSE3::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
|
||||
#elif (SSE_VERSION == 4)
|
||||
# elif (SSE_VERSION == 4)
|
||||
inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
|
||||
#endif
|
||||
# endif
|
||||
{
|
||||
const uint8_t * const remap = bp->remap;
|
||||
Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left;
|
||||
const uint8_t *const remap = bp->remap;
|
||||
Colour *dst_line = (Colour *)bp->dst + bp->top * bp->pitch + bp->left;
|
||||
int effective_width = bp->width;
|
||||
|
||||
/* Find where to start reading in the source sprite. */
|
||||
const SpriteData * const sd = (const SpriteData *) bp->sprite;
|
||||
const SpriteInfo * const si = &sd->infos[zoom];
|
||||
const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width;
|
||||
const Colour *src_rgba_line = (const Colour *) ((const uint8_t *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size);
|
||||
const SpriteData *const sd = (const SpriteData *)bp->sprite;
|
||||
const SpriteInfo *const si = &sd->infos[zoom];
|
||||
const MapValue *src_mv_line = (const MapValue *)&sd->data[si->mv_offset] + bp->skip_top * si->sprite_width;
|
||||
const Colour *src_rgba_line = (const Colour *)((const uint8_t *)&sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size);
|
||||
|
||||
if (read_mode != RM_WITH_MARGIN) {
|
||||
src_rgba_line += bp->skip_left;
|
||||
|
@ -238,22 +248,22 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
const MapValue *src_mv = src_mv_line;
|
||||
|
||||
/* Load these variables into register before loop. */
|
||||
const __m128i alpha_and = ALPHA_AND_MASK;
|
||||
#define ALPHA_BLEND_PARAM_3 alpha_and
|
||||
#if (SSE_VERSION == 2)
|
||||
const __m128i clear_hi = CLEAR_HIGH_BYTE_MASK;
|
||||
#define ALPHA_BLEND_PARAM_1 alpha_and
|
||||
#define ALPHA_BLEND_PARAM_2 clear_hi
|
||||
#define DARKEN_PARAM_1 tr_nom_base
|
||||
#define DARKEN_PARAM_2 tr_nom_base
|
||||
#else
|
||||
const __m128i a_cm = ALPHA_CONTROL_MASK;
|
||||
const __m128i alpha_and = ALPHA_AND_MASK;
|
||||
# define ALPHA_BLEND_PARAM_3 alpha_and
|
||||
# if (SSE_VERSION == 2)
|
||||
const __m128i clear_hi = CLEAR_HIGH_BYTE_MASK;
|
||||
# define ALPHA_BLEND_PARAM_1 alpha_and
|
||||
# define ALPHA_BLEND_PARAM_2 clear_hi
|
||||
# define DARKEN_PARAM_1 tr_nom_base
|
||||
# define DARKEN_PARAM_2 tr_nom_base
|
||||
# else
|
||||
const __m128i a_cm = ALPHA_CONTROL_MASK;
|
||||
const __m128i pack_low_cm = PACK_LOW_CONTROL_MASK;
|
||||
#define ALPHA_BLEND_PARAM_1 a_cm
|
||||
#define ALPHA_BLEND_PARAM_2 pack_low_cm
|
||||
#define DARKEN_PARAM_1 a_cm
|
||||
#define DARKEN_PARAM_2 tr_nom_base
|
||||
#endif
|
||||
# define ALPHA_BLEND_PARAM_1 a_cm
|
||||
# define ALPHA_BLEND_PARAM_2 pack_low_cm
|
||||
# define DARKEN_PARAM_1 a_cm
|
||||
# define DARKEN_PARAM_2 tr_nom_base
|
||||
# endif
|
||||
const __m128i tr_nom_base = TRANSPARENT_NOM_BASE;
|
||||
|
||||
for (int y = bp->height; y != 0; y--) {
|
||||
|
@ -267,8 +277,8 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
dst += src_rgba_line[0].data;
|
||||
if (mode == BlitterMode::ColourRemap || mode == BlitterMode::CrashRemap) src_mv += src_rgba_line[0].data;
|
||||
const int width_diff = si->sprite_width - bp->width;
|
||||
effective_width = bp->width - (int) src_rgba_line[0].data;
|
||||
const int delta_diff = (int) src_rgba_line[1].data - width_diff;
|
||||
effective_width = bp->width - (int)src_rgba_line[0].data;
|
||||
const int delta_diff = (int)src_rgba_line[1].data - width_diff;
|
||||
const int new_width = effective_width - delta_diff;
|
||||
effective_width = delta_diff > 0 ? new_width : effective_width;
|
||||
if (effective_width <= 0) goto next_line;
|
||||
|
@ -277,7 +287,7 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
switch (mode) {
|
||||
default:
|
||||
if (!translucent) {
|
||||
for (uint x = (uint) effective_width; x > 0; x--) {
|
||||
for (uint x = (uint)effective_width; x > 0; x--) {
|
||||
if (src->a) *dst = *src;
|
||||
src++;
|
||||
dst++;
|
||||
|
@ -285,10 +295,10 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
break;
|
||||
}
|
||||
|
||||
for (uint x = (uint) effective_width / 2; x > 0; x--) {
|
||||
__m128i srcABCD = _mm_loadl_epi64((const __m128i*) src);
|
||||
__m128i dstABCD = _mm_loadl_epi64((__m128i*) dst);
|
||||
_mm_storel_epi64((__m128i*) dst, AlphaBlendTwoPixels(srcABCD, dstABCD, ALPHA_BLEND_PARAM_1, ALPHA_BLEND_PARAM_2, ALPHA_BLEND_PARAM_3));
|
||||
for (uint x = (uint)effective_width / 2; x > 0; x--) {
|
||||
__m128i srcABCD = _mm_loadl_epi64((const __m128i *)src);
|
||||
__m128i dstABCD = _mm_loadl_epi64((__m128i *)dst);
|
||||
_mm_storel_epi64((__m128i *)dst, AlphaBlendTwoPixels(srcABCD, dstABCD, ALPHA_BLEND_PARAM_1, ALPHA_BLEND_PARAM_2, ALPHA_BLEND_PARAM_3));
|
||||
src += 2;
|
||||
dst += 2;
|
||||
}
|
||||
|
@ -301,16 +311,16 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
break;
|
||||
|
||||
case BlitterMode::ColourRemap:
|
||||
#if (SSE_VERSION >= 3)
|
||||
for (uint x = (uint) effective_width / 2; x > 0; x--) {
|
||||
__m128i srcABCD = _mm_loadl_epi64((const __m128i*) src);
|
||||
__m128i dstABCD = _mm_loadl_epi64((__m128i*) dst);
|
||||
uint32_t mvX2 = *((uint32_t *) const_cast<MapValue *>(src_mv));
|
||||
# if (SSE_VERSION >= 3)
|
||||
for (uint x = (uint)effective_width / 2; x > 0; x--) {
|
||||
__m128i srcABCD = _mm_loadl_epi64((const __m128i *)src);
|
||||
__m128i dstABCD = _mm_loadl_epi64((__m128i *)dst);
|
||||
uint32_t mvX2 = *((uint32_t *)const_cast<MapValue *>(src_mv));
|
||||
|
||||
/* Remap colours. */
|
||||
if (mvX2 & 0x00FF00FF) {
|
||||
/* Written so the compiler uses CMOV. */
|
||||
#define CMOV_REMAP(m_colour, m_colour_init, m_src, m_m) \
|
||||
/* Written so the compiler uses CMOV. */
|
||||
# define CMOV_REMAP(m_colour, m_colour_init, m_src, m_m) \
|
||||
Colour m_colour = m_colour_init; \
|
||||
{ \
|
||||
const Colour srcm = (Colour) (m_src); \
|
||||
|
@ -320,37 +330,37 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
m_colour = r == 0 ? m_colour : cmap; \
|
||||
m_colour = m != 0 ? m_colour : srcm; \
|
||||
}
|
||||
#ifdef POINTER_IS_64BIT
|
||||
# ifdef POINTER_IS_64BIT
|
||||
uint64_t srcs = _mm_cvtsi128_si64(srcABCD);
|
||||
uint64_t remapped_src = 0;
|
||||
CMOV_REMAP(c0, 0, srcs, mvX2);
|
||||
remapped_src = c0.data;
|
||||
CMOV_REMAP(c1, 0, srcs >> 32, mvX2 >> 16);
|
||||
remapped_src |= (uint64_t) c1.data << 32;
|
||||
remapped_src |= (uint64_t)c1.data << 32;
|
||||
srcABCD = _mm_cvtsi64_si128(remapped_src);
|
||||
#else
|
||||
# else
|
||||
Colour remapped_src[2];
|
||||
CMOV_REMAP(c0, 0, _mm_cvtsi128_si32(srcABCD), mvX2);
|
||||
remapped_src[0] = c0.data;
|
||||
CMOV_REMAP(c1, 0, src[1], mvX2 >> 16);
|
||||
remapped_src[1] = c1.data;
|
||||
srcABCD = _mm_loadl_epi64((__m128i*) &remapped_src);
|
||||
#endif
|
||||
srcABCD = _mm_loadl_epi64((__m128i *)&remapped_src);
|
||||
# endif
|
||||
|
||||
if ((mvX2 & 0xFF00FF00) != 0x80008000) srcABCD = AdjustBrightnessOfTwoPixels(srcABCD, mvX2);
|
||||
}
|
||||
|
||||
/* Blend colours. */
|
||||
_mm_storel_epi64((__m128i *) dst, AlphaBlendTwoPixels(srcABCD, dstABCD, ALPHA_BLEND_PARAM_1, ALPHA_BLEND_PARAM_2, ALPHA_BLEND_PARAM_3));
|
||||
_mm_storel_epi64((__m128i *)dst, AlphaBlendTwoPixels(srcABCD, dstABCD, ALPHA_BLEND_PARAM_1, ALPHA_BLEND_PARAM_2, ALPHA_BLEND_PARAM_3));
|
||||
dst += 2;
|
||||
src += 2;
|
||||
src_mv += 2;
|
||||
}
|
||||
|
||||
if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) {
|
||||
#else
|
||||
for (uint x = (uint) effective_width; x > 0; x--) {
|
||||
#endif
|
||||
# else
|
||||
for (uint x = (uint)effective_width; x > 0; x--) {
|
||||
# endif
|
||||
/* In case the m-channel is zero, do not remap this pixel in any way. */
|
||||
__m128i srcABCD;
|
||||
if (src_mv->m) {
|
||||
|
@ -368,26 +378,26 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
} else {
|
||||
srcABCD = _mm_cvtsi32_si128(src->data);
|
||||
if (src->a < 255) {
|
||||
bmcr_alpha_blend_single:
|
||||
bmcr_alpha_blend_single:
|
||||
__m128i dstABCD = _mm_cvtsi32_si128(dst->data);
|
||||
srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, ALPHA_BLEND_PARAM_1, ALPHA_BLEND_PARAM_2, ALPHA_BLEND_PARAM_3);
|
||||
}
|
||||
dst->data = _mm_cvtsi128_si32(srcABCD);
|
||||
}
|
||||
#if (SSE_VERSION == 2)
|
||||
# if (SSE_VERSION == 2)
|
||||
src_mv++;
|
||||
dst++;
|
||||
src++;
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
break;
|
||||
|
||||
case BlitterMode::Transparent:
|
||||
/* Make the current colour a bit more black, so it looks like this image is transparent. */
|
||||
for (uint x = (uint) bp->width / 2; x > 0; x--) {
|
||||
__m128i srcABCD = _mm_loadl_epi64((const __m128i*) src);
|
||||
__m128i dstABCD = _mm_loadl_epi64((__m128i*) dst);
|
||||
_mm_storel_epi64((__m128i *) dst, DarkenTwoPixels(srcABCD, dstABCD, DARKEN_PARAM_1, DARKEN_PARAM_2));
|
||||
for (uint x = (uint)bp->width / 2; x > 0; x--) {
|
||||
__m128i srcABCD = _mm_loadl_epi64((const __m128i *)src);
|
||||
__m128i dstABCD = _mm_loadl_epi64((__m128i *)dst);
|
||||
_mm_storel_epi64((__m128i *)dst, DarkenTwoPixels(srcABCD, dstABCD, DARKEN_PARAM_1, DARKEN_PARAM_2));
|
||||
src += 2;
|
||||
dst += 2;
|
||||
}
|
||||
|
@ -401,7 +411,7 @@ bmcr_alpha_blend_single:
|
|||
|
||||
case BlitterMode::TransparentRemap:
|
||||
/* Apply custom transparency remap. */
|
||||
for (uint x = (uint) bp->width; x > 0; x--) {
|
||||
for (uint x = (uint)bp->width; x > 0; x--) {
|
||||
if (src->a != 0) {
|
||||
*dst = this->LookupColourInPalette(remap[GetNearestColourIndex(*dst)]);
|
||||
}
|
||||
|
@ -412,7 +422,7 @@ bmcr_alpha_blend_single:
|
|||
break;
|
||||
|
||||
case BlitterMode::CrashRemap:
|
||||
for (uint x = (uint) bp->width; x > 0; x--) {
|
||||
for (uint x = (uint)bp->width; x > 0; x--) {
|
||||
if (src_mv->m == 0) {
|
||||
if (src->a != 0) {
|
||||
uint8_t g = MakeDark(src->r, src->g, src->b);
|
||||
|
@ -429,7 +439,7 @@ bmcr_alpha_blend_single:
|
|||
break;
|
||||
|
||||
case BlitterMode::BlackRemap:
|
||||
for (uint x = (uint) bp->width; x > 0; x--) {
|
||||
for (uint x = (uint)bp->width; x > 0; x--) {
|
||||
if (src->a != 0) {
|
||||
*dst = Colour(0, 0, 0);
|
||||
}
|
||||
|
@ -440,9 +450,9 @@ bmcr_alpha_blend_single:
|
|||
break;
|
||||
}
|
||||
|
||||
next_line:
|
||||
next_line:
|
||||
if (mode == BlitterMode::ColourRemap || mode == BlitterMode::CrashRemap) src_mv_line += si->sprite_width;
|
||||
src_rgba_line = (const Colour*) ((const uint8_t*) src_rgba_line + si->sprite_line_size);
|
||||
src_rgba_line = (const Colour *)((const uint8_t *)src_rgba_line + si->sprite_line_size);
|
||||
dst_line += bp->pitch;
|
||||
}
|
||||
}
|
||||
|
@ -455,25 +465,29 @@ IGNORE_UNINITIALIZED_WARNING_STOP
|
|||
* @param mode blitter mode
|
||||
* @param zoom zoom level at which we are drawing
|
||||
*/
|
||||
#if (SSE_VERSION == 2)
|
||||
# if (SSE_VERSION == 2)
|
||||
void Blitter_32bppSSE2::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
||||
#elif (SSE_VERSION == 3)
|
||||
# elif (SSE_VERSION == 3)
|
||||
void Blitter_32bppSSSE3::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
||||
#elif (SSE_VERSION == 4)
|
||||
# elif (SSE_VERSION == 4)
|
||||
void Blitter_32bppSSE4::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
||||
#endif
|
||||
# endif
|
||||
{
|
||||
switch (mode) {
|
||||
default: {
|
||||
if (bp->skip_left != 0 || bp->width <= MARGIN_NORMAL_THRESHOLD) {
|
||||
bm_normal:
|
||||
const BlockType bt_last = (BlockType) (bp->width & 1);
|
||||
bm_normal:
|
||||
const BlockType bt_last = (BlockType)(bp->width & 1);
|
||||
switch (bt_last) {
|
||||
default: Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true>(bp, zoom); return;
|
||||
case BT_ODD: Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true>(bp, zoom); return;
|
||||
default:
|
||||
Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true>(bp, zoom);
|
||||
return;
|
||||
case BT_ODD:
|
||||
Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true>(bp, zoom);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (((const Blitter_32bppSSE_Base::SpriteData *) bp->sprite)->flags.Test(SpriteFlag::Translucent)) {
|
||||
if (((const Blitter_32bppSSE_Base::SpriteData *)bp->sprite)->flags.Test(SpriteFlag::Translucent)) {
|
||||
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true>(bp, zoom);
|
||||
} else {
|
||||
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false>(bp, zoom);
|
||||
|
@ -483,19 +497,29 @@ bm_normal:
|
|||
break;
|
||||
}
|
||||
case BlitterMode::ColourRemap:
|
||||
if (((const Blitter_32bppSSE_Base::SpriteData *) bp->sprite)->flags.Test(SpriteFlag::NoRemap)) goto bm_normal;
|
||||
if (((const Blitter_32bppSSE_Base::SpriteData *)bp->sprite)->flags.Test(SpriteFlag::NoRemap)) goto bm_normal;
|
||||
if (bp->skip_left != 0 || bp->width <= MARGIN_REMAP_THRESHOLD) {
|
||||
Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true>(bp, zoom); return;
|
||||
Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true>(bp, zoom);
|
||||
return;
|
||||
} else {
|
||||
Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true>(bp, zoom); return;
|
||||
Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true>(bp, zoom);
|
||||
return;
|
||||
}
|
||||
case BlitterMode::Transparent: Draw<BlitterMode::Transparent, RM_NONE, BT_NONE, true>(bp, zoom); return;
|
||||
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap, RM_NONE, BT_NONE, true>(bp, zoom); return;
|
||||
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap, RM_NONE, BT_NONE, true>(bp, zoom); return;
|
||||
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap, RM_NONE, BT_NONE, true>(bp, zoom); return;
|
||||
case BlitterMode::Transparent:
|
||||
Draw<BlitterMode::Transparent, RM_NONE, BT_NONE, true>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::TransparentRemap:
|
||||
Draw<BlitterMode::TransparentRemap, RM_NONE, BT_NONE, true>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::CrashRemap:
|
||||
Draw<BlitterMode::CrashRemap, RM_NONE, BT_NONE, true>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::BlackRemap:
|
||||
Draw<BlitterMode::BlackRemap, RM_NONE, BT_NONE, true>(bp, zoom);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* FULL_ANIMATION */
|
||||
# endif /* FULL_ANIMATION */
|
||||
|
||||
#endif /* WITH_SSE */
|
||||
#endif /* BLITTER_32BPP_SSE_FUNC_HPP */
|
||||
|
|
|
@ -18,18 +18,18 @@
|
|||
|
||||
#ifdef WITH_SSE
|
||||
|
||||
#include "32bpp_simple.hpp"
|
||||
#if (SSE_VERSION == 2)
|
||||
#include <emmintrin.h>
|
||||
#elif (SSE_VERSION == 3)
|
||||
#include <tmmintrin.h>
|
||||
#elif (SSE_VERSION == 4)
|
||||
#include <smmintrin.h>
|
||||
#endif
|
||||
# include "32bpp_simple.hpp"
|
||||
# if (SSE_VERSION == 2)
|
||||
# include <emmintrin.h>
|
||||
# elif (SSE_VERSION == 3)
|
||||
# include <tmmintrin.h>
|
||||
# elif (SSE_VERSION == 4)
|
||||
# include <smmintrin.h>
|
||||
# endif
|
||||
|
||||
#define META_LENGTH 2 ///< Number of uint32_t inserted before each line of pixels in a sprite.
|
||||
#define MARGIN_NORMAL_THRESHOLD (zoom == ZOOM_LVL_OUT_8X ? 8 : 4) ///< Minimum width to use margins with BlitterMode::Normal.
|
||||
#define MARGIN_REMAP_THRESHOLD 4 ///< Minimum width to use margins with BlitterMode::ColourRemap.
|
||||
# define META_LENGTH 2 ///< Number of uint32_t inserted before each line of pixels in a sprite.
|
||||
# define MARGIN_NORMAL_THRESHOLD (zoom == ZOOM_LVL_OUT_8X ? 8 : 4) ///< Minimum width to use margins with BlitterMode::Normal.
|
||||
# define MARGIN_REMAP_THRESHOLD 4 ///< Minimum width to use margins with BlitterMode::ColourRemap.
|
||||
|
||||
typedef union alignas(16) um128i {
|
||||
__m128i m128i;
|
||||
|
@ -39,17 +39,17 @@ typedef union alignas(16) um128i {
|
|||
uint64_t m128i_u64[2];
|
||||
} um128i;
|
||||
|
||||
#define CLEAR_HIGH_BYTE_MASK _mm_setr_epi8(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0)
|
||||
#define ALPHA_CONTROL_MASK _mm_setr_epi8( 6, 7, 6, 7, 6, 7, -1, -1, 14, 15, 14, 15, 14, 15, -1, -1)
|
||||
#define PACK_LOW_CONTROL_MASK _mm_setr_epi8( 0, 2, 4, 6, 8, 10, 12, 14, -1, -1, -1, -1, -1, -1, -1, -1)
|
||||
#define PACK_HIGH_CONTROL_MASK _mm_setr_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 0, 2, 4, -1, 8, 10, 12, -1)
|
||||
#define BRIGHTNESS_LOW_CONTROL_MASK _mm_setr_epi8( 1, 2, 1, 2, 1, 2, 0, 2, 3, 2, 3, 2, 3, 2, 0, 2)
|
||||
#define BRIGHTNESS_DIV_CLEANER _mm_setr_epi8(-1, 1, -1, 1, -1, 1, -1, 0, -1, 1, -1, 1, -1, 1, -1, 0)
|
||||
#define OVERBRIGHT_PRESENCE_MASK _mm_setr_epi8( 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0)
|
||||
#define OVERBRIGHT_VALUE_MASK _mm_setr_epi8(-1, 0, -1, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, 0)
|
||||
#define OVERBRIGHT_CONTROL_MASK _mm_setr_epi8( 0, 1, 0, 1, 0, 1, 7, 7, 2, 3, 2, 3, 2, 3, 7, 7)
|
||||
#define TRANSPARENT_NOM_BASE _mm_setr_epi16(256, 256, 256, 256, 256, 256, 256, 256)
|
||||
#define ALPHA_AND_MASK _mm_setr_epi16( 0, 0, 0, -1, 0, 0, 0, -1)
|
||||
# define CLEAR_HIGH_BYTE_MASK _mm_setr_epi8(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0)
|
||||
# define ALPHA_CONTROL_MASK _mm_setr_epi8( 6, 7, 6, 7, 6, 7, -1, -1, 14, 15, 14, 15, 14, 15, -1, -1)
|
||||
# define PACK_LOW_CONTROL_MASK _mm_setr_epi8( 0, 2, 4, 6, 8, 10, 12, 14, -1, -1, -1, -1, -1, -1, -1, -1)
|
||||
# define PACK_HIGH_CONTROL_MASK _mm_setr_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 0, 2, 4, -1, 8, 10, 12, -1)
|
||||
# define BRIGHTNESS_LOW_CONTROL_MASK _mm_setr_epi8( 1, 2, 1, 2, 1, 2, 0, 2, 3, 2, 3, 2, 3, 2, 0, 2)
|
||||
# define BRIGHTNESS_DIV_CLEANER _mm_setr_epi8(-1, 1, -1, 1, -1, 1, -1, 0, -1, 1, -1, 1, -1, 1, -1, 0)
|
||||
# define OVERBRIGHT_PRESENCE_MASK _mm_setr_epi8( 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0)
|
||||
# define OVERBRIGHT_VALUE_MASK _mm_setr_epi8(-1, 0, -1, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, 0)
|
||||
# define OVERBRIGHT_CONTROL_MASK _mm_setr_epi8( 0, 1, 0, 1, 0, 1, 7, 7, 2, 3, 2, 3, 2, 3, 7, 7)
|
||||
# define TRANSPARENT_NOM_BASE _mm_setr_epi16(256, 256, 256, 256, 256, 256, 256, 256)
|
||||
# define ALPHA_AND_MASK _mm_setr_epi16( 0, 0, 0, -1, 0, 0, 0, -1)
|
||||
|
||||
#endif /* WITH_SSE */
|
||||
#endif /* BLITTER_32BPP_SSE_TYPE_H */
|
||||
|
|
|
@ -9,13 +9,15 @@
|
|||
|
||||
#ifdef WITH_SSE
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../zoom_func.h"
|
||||
#include "../settings_type.h"
|
||||
#include "32bpp_ssse3.hpp"
|
||||
#include "32bpp_sse_func.hpp"
|
||||
# include "../stdafx.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
# include "32bpp_ssse3.hpp"
|
||||
|
||||
# include "../settings_type.h"
|
||||
# include "../zoom_func.h"
|
||||
# include "32bpp_sse_func.hpp"
|
||||
|
||||
# include "../safeguards.h"
|
||||
|
||||
/** Instantiation of the SSSE3 32bpp blitter factory. */
|
||||
static FBlitter_32bppSSSE3 iFBlitter_32bppSSSE3;
|
||||
|
|
|
@ -12,19 +12,19 @@
|
|||
|
||||
#ifdef WITH_SSE
|
||||
|
||||
#ifndef SSE_VERSION
|
||||
#define SSE_VERSION 3
|
||||
#endif
|
||||
# ifndef SSE_VERSION
|
||||
# define SSE_VERSION 3
|
||||
# endif
|
||||
|
||||
#ifndef SSE_TARGET
|
||||
#define SSE_TARGET "ssse3"
|
||||
#endif
|
||||
# ifndef SSE_TARGET
|
||||
# define SSE_TARGET "ssse3"
|
||||
# endif
|
||||
|
||||
#ifndef FULL_ANIMATION
|
||||
#define FULL_ANIMATION 0
|
||||
#endif
|
||||
# ifndef FULL_ANIMATION
|
||||
# define FULL_ANIMATION 0
|
||||
# endif
|
||||
|
||||
#include "32bpp_sse2.hpp"
|
||||
# include "32bpp_sse2.hpp"
|
||||
|
||||
/** The SSSE3 32 bpp blitter (without palette animation). */
|
||||
class Blitter_32bppSSSE3 : public Blitter_32bppSSE2 {
|
||||
|
@ -32,14 +32,22 @@ public:
|
|||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
||||
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent>
|
||||
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
||||
std::string_view GetName() override { return "32bpp-ssse3"; }
|
||||
|
||||
std::string_view GetName() override
|
||||
{
|
||||
return "32bpp-ssse3";
|
||||
}
|
||||
};
|
||||
|
||||
/** Factory for the SSSE3 32 bpp blitter (without palette animation). */
|
||||
class FBlitter_32bppSSSE3: public BlitterFactory {
|
||||
class FBlitter_32bppSSSE3 : public BlitterFactory {
|
||||
public:
|
||||
FBlitter_32bppSSSE3() : BlitterFactory("32bpp-ssse3", "32bpp SSSE3 Blitter (no palette animation)", HasCPUIDFlag(1, 2, 9)) {}
|
||||
std::unique_ptr<Blitter> CreateInstance() override { return std::make_unique<Blitter_32bppSSSE3>(); }
|
||||
|
||||
std::unique_ptr<Blitter> CreateInstance() override
|
||||
{
|
||||
return std::make_unique<Blitter_32bppSSSE3>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* WITH_SSE */
|
||||
|
|
|
@ -8,25 +8,25 @@
|
|||
/** @file 40bpp_optimized.cpp Implementation of the optimized 40 bpp blitter. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../zoom_func.h"
|
||||
|
||||
#include "40bpp_anim.hpp"
|
||||
|
||||
#include "../palette_func.h"
|
||||
#include "../settings_type.h"
|
||||
#include "../video/video_driver.hpp"
|
||||
#include "../palette_func.h"
|
||||
#include "40bpp_anim.hpp"
|
||||
#include "../zoom_func.h"
|
||||
#include "common.hpp"
|
||||
|
||||
#include "../table/sprites.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
|
||||
/** Instantiation of the 40bpp with animation blitter factory. */
|
||||
static FBlitter_40bppAnim iFBlitter_40bppAnim;
|
||||
|
||||
/** Cached black value. */
|
||||
static const Colour _black_colour(0, 0, 0);
|
||||
|
||||
|
||||
void Blitter_40bppAnim::SetPixel(void *video, int x, int y, uint8_t colour)
|
||||
{
|
||||
if (_screen_disable_anim) {
|
||||
|
@ -100,7 +100,7 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
/* src_n : each line begins with uint32_t n = 'number of bytes in this line',
|
||||
* then interleaved stream of 'm' and 'n' channels. 'm' is remap,
|
||||
* 'n' is number of bytes with the same alpha channel class */
|
||||
const uint16_t *src_n = (const uint16_t *)(src->data + src->offset[zoom][1]);
|
||||
const uint16_t *src_n = (const uint16_t *)(src->data + src->offset[zoom][1]);
|
||||
|
||||
/* skip upper lines in src_px and src_n */
|
||||
for (uint i = bp->skip_top; i != 0; i--) {
|
||||
|
@ -178,7 +178,7 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
continue;
|
||||
}
|
||||
|
||||
draw:;
|
||||
draw:;
|
||||
|
||||
switch (mode) {
|
||||
case BlitterMode::ColourRemap:
|
||||
|
@ -316,7 +316,7 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
|||
dst = dst_ln;
|
||||
anim = anim_ln;
|
||||
src_px = src_px_ln;
|
||||
src_n = src_n_ln;
|
||||
src_n = src_n_ln;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -338,13 +338,26 @@ void Blitter_40bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomL
|
|||
}
|
||||
|
||||
switch (mode) {
|
||||
default: NOT_REACHED();
|
||||
case BlitterMode::Normal: Draw<BlitterMode::Normal>(bp, zoom); return;
|
||||
case BlitterMode::ColourRemap: Draw<BlitterMode::ColourRemap>(bp, zoom); return;
|
||||
case BlitterMode::Transparent: Draw<BlitterMode::Transparent>(bp, zoom); return;
|
||||
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap>(bp, zoom); return;
|
||||
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap>(bp, zoom); return;
|
||||
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap>(bp, zoom); return;
|
||||
default:
|
||||
NOT_REACHED();
|
||||
case BlitterMode::Normal:
|
||||
Draw<BlitterMode::Normal>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::ColourRemap:
|
||||
Draw<BlitterMode::ColourRemap>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::Transparent:
|
||||
Draw<BlitterMode::Transparent>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::TransparentRemap:
|
||||
Draw<BlitterMode::TransparentRemap>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::CrashRemap:
|
||||
Draw<BlitterMode::CrashRemap>(bp, zoom);
|
||||
return;
|
||||
case BlitterMode::BlackRemap:
|
||||
Draw<BlitterMode::BlackRemap>(bp, zoom);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,7 +415,6 @@ Sprite *Blitter_40bppAnim::Encode(const SpriteLoader::SpriteCollection &sprite,
|
|||
return this->EncodeInternal<false>(sprite, allocator);
|
||||
}
|
||||
|
||||
|
||||
void Blitter_40bppAnim::CopyFromBuffer(void *video, const void *src, int width, int height)
|
||||
{
|
||||
assert(!_screen_disable_anim);
|
||||
|
|
|
@ -10,14 +10,12 @@
|
|||
#ifndef BLITTER_40BPP_OPTIMIZED_HPP
|
||||
#define BLITTER_40BPP_OPTIMIZED_HPP
|
||||
|
||||
|
||||
#include "32bpp_optimized.hpp"
|
||||
#include "../video/video_driver.hpp"
|
||||
#include "32bpp_optimized.hpp"
|
||||
|
||||
/** The optimized 40 bpp blitter (for OpenGL video driver). */
|
||||
class Blitter_40bppAnim : public Blitter_32bppOptimized {
|
||||
public:
|
||||
|
||||
void SetPixel(void *video, int x, int y, uint8_t colour) override;
|
||||
void DrawRect(void *video, int width, int height, uint8_t colour) override;
|
||||
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) override;
|
||||
|
@ -32,16 +30,19 @@ public:
|
|||
Blitter::PaletteAnimation UsePaletteAnimation() override;
|
||||
bool NeedsAnimationBuffer() override;
|
||||
|
||||
std::string_view GetName() override { return "40bpp-anim"; }
|
||||
std::string_view GetName() override
|
||||
{
|
||||
return "40bpp-anim";
|
||||
}
|
||||
|
||||
template <BlitterMode mode> void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
||||
template <BlitterMode mode>
|
||||
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
||||
|
||||
protected:
|
||||
static inline Colour RealizeBlendedColour(uint8_t anim, Colour c)
|
||||
{
|
||||
return anim != 0 ? AdjustBrightness(LookupColourInPalette(anim), GetColourBrightness(c)) : c;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/** Factory for the 40 bpp animated blitter (for OpenGL). */
|
||||
|
@ -54,7 +55,11 @@ protected:
|
|||
|
||||
public:
|
||||
FBlitter_40bppAnim() : BlitterFactory("40bpp-anim", "40bpp Animation Blitter (OpenGL)") {}
|
||||
std::unique_ptr<Blitter> CreateInstance() override { return std::make_unique<Blitter_40bppAnim>(); }
|
||||
|
||||
std::unique_ptr<Blitter> CreateInstance() override
|
||||
{
|
||||
return std::make_unique<Blitter_40bppAnim>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* BLITTER_40BPP_OPTIMIZED_HPP */
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
/** @file 8bpp_base.cpp Implementation of the base for all 8 bpp blitters. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../gfx_func.h"
|
||||
|
||||
#include "8bpp_base.hpp"
|
||||
|
||||
#include "../gfx_func.h"
|
||||
#include "common.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
|
|
@ -15,7 +15,11 @@
|
|||
/** Base for all 8bpp blitters. */
|
||||
class Blitter_8bppBase : public Blitter {
|
||||
public:
|
||||
uint8_t GetScreenDepth() override { return 8; }
|
||||
uint8_t GetScreenDepth() override
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override;
|
||||
void *MoveTo(void *video, int x, int y) override;
|
||||
void SetPixel(void *video, int x, int y, uint8_t colour) override;
|
||||
|
|
|
@ -8,11 +8,13 @@
|
|||
/** @file 8bpp_optimized.cpp Implementation of the optimized 8 bpp blitter. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../zoom_func.h"
|
||||
#include "../settings_type.h"
|
||||
|
||||
#include "8bpp_optimized.hpp"
|
||||
|
||||
#include "../core/math_func.hpp"
|
||||
#include "../core/mem_func.hpp"
|
||||
#include "8bpp_optimized.hpp"
|
||||
#include "../settings_type.h"
|
||||
#include "../zoom_func.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
|
@ -90,7 +92,8 @@ void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Z
|
|||
do {
|
||||
uint m = remap[*src];
|
||||
if (m != 0) *dst = m;
|
||||
dst++; src++;
|
||||
dst++;
|
||||
src++;
|
||||
} while (--pixels != 0);
|
||||
break;
|
||||
}
|
||||
|
@ -113,7 +116,8 @@ void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Z
|
|||
|
||||
default:
|
||||
MemCpyT(dst, src, pixels);
|
||||
dst += pixels; src += pixels;
|
||||
dst += pixels;
|
||||
src += pixels;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +163,7 @@ Sprite *Blitter_8bppOptimized::Encode(const SpriteLoader::SpriteCollection &spri
|
|||
|
||||
/* cache values, because compiler can't cache it */
|
||||
int scaled_height = sprite[i].height;
|
||||
int scaled_width = sprite[i].width;
|
||||
int scaled_width = sprite[i].width;
|
||||
|
||||
for (int y = 0; y < scaled_height; y++) {
|
||||
uint trans = 0;
|
||||
|
@ -207,8 +211,10 @@ Sprite *Blitter_8bppOptimized::Encode(const SpriteLoader::SpriteCollection &spri
|
|||
if (count_dst != nullptr) *count_dst = pixels;
|
||||
|
||||
/* Write line-ending */
|
||||
*dst = 0; dst++;
|
||||
*dst = 0; dst++;
|
||||
*dst = 0;
|
||||
dst++;
|
||||
*dst = 0;
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,7 +227,7 @@ Sprite *Blitter_8bppOptimized::Encode(const SpriteLoader::SpriteCollection &spri
|
|||
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + size);
|
||||
|
||||
dest_sprite->height = sprite[ZOOM_LVL_MIN].height;
|
||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
||||
dest_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
|
||||
dest_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
|
||||
memcpy(dest_sprite->data, temp_dst, size);
|
||||
|
|
|
@ -19,20 +19,27 @@ public:
|
|||
/** Data stored about a (single) sprite. */
|
||||
struct SpriteData {
|
||||
uint32_t offset[ZOOM_LVL_END]; ///< Offsets (from .data) to streams for different zoom levels.
|
||||
uint8_t data[]; ///< Data, all zoomlevels.
|
||||
uint8_t data[]; ///< Data, all zoomlevels.
|
||||
};
|
||||
|
||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
||||
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
|
||||
|
||||
std::string_view GetName() override { return "8bpp-optimized"; }
|
||||
std::string_view GetName() override
|
||||
{
|
||||
return "8bpp-optimized";
|
||||
}
|
||||
};
|
||||
|
||||
/** Factory for the 8bpp blitter optimised for speed. */
|
||||
class FBlitter_8bppOptimized : public BlitterFactory {
|
||||
public:
|
||||
FBlitter_8bppOptimized() : BlitterFactory("8bpp-optimized", "8bpp Optimized Blitter (compression + all-ZoomLevel cache)") {}
|
||||
std::unique_ptr<Blitter> CreateInstance() override { return std::make_unique<Blitter_8bppOptimized>(); }
|
||||
|
||||
std::unique_ptr<Blitter> CreateInstance() override
|
||||
{
|
||||
return std::make_unique<Blitter_8bppOptimized>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* BLITTER_8BPP_OPTIMIZED_HPP */
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
/** @file 8bpp_simple.cpp Implementation of the simple 8 bpp blitter. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../zoom_func.h"
|
||||
|
||||
#include "8bpp_simple.hpp"
|
||||
|
||||
#include "../zoom_func.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/** Instantiation of the simple 8bpp blitter factory. */
|
||||
|
@ -67,7 +69,7 @@ Sprite *Blitter_8bppSimple::Encode(const SpriteLoader::SpriteCollection &sprite,
|
|||
dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + static_cast<size_t>(sprite[ZOOM_LVL_MIN].height) * static_cast<size_t>(sprite[ZOOM_LVL_MIN].width));
|
||||
|
||||
dest_sprite->height = sprite[ZOOM_LVL_MIN].height;
|
||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
||||
dest_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
|
||||
dest_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
|
||||
|
||||
|
|
|
@ -19,14 +19,21 @@ public:
|
|||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
||||
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
|
||||
|
||||
std::string_view GetName() override { return "8bpp-simple"; }
|
||||
std::string_view GetName() override
|
||||
{
|
||||
return "8bpp-simple";
|
||||
}
|
||||
};
|
||||
|
||||
/** Factory for the most trivial 8bpp blitter. */
|
||||
class FBlitter_8bppSimple : public BlitterFactory {
|
||||
public:
|
||||
FBlitter_8bppSimple() : BlitterFactory("8bpp-simple", "8bpp Simple Blitter (relative slow, but never wrong)") {}
|
||||
std::unique_ptr<Blitter> CreateInstance() override { return std::make_unique<Blitter_8bppSimple>(); }
|
||||
|
||||
std::unique_ptr<Blitter> CreateInstance() override
|
||||
{
|
||||
return std::make_unique<Blitter_8bppSimple>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* BLITTER_8BPP_SIMPLE_HPP */
|
||||
|
|
|
@ -31,19 +31,19 @@ public:
|
|||
/** Parameters related to blitting. */
|
||||
struct BlitterParams {
|
||||
const void *sprite; ///< Pointer to the sprite how ever the encoder stored it
|
||||
const uint8_t *remap; ///< XXX -- Temporary storage for remap array
|
||||
const uint8_t *remap; ///< XXX -- Temporary storage for remap array
|
||||
|
||||
int skip_left; ///< How much pixels of the source to skip on the left (based on zoom of dst)
|
||||
int skip_top; ///< How much pixels of the source to skip on the top (based on zoom of dst)
|
||||
int width; ///< The width in pixels that needs to be drawn to dst
|
||||
int height; ///< The height in pixels that needs to be drawn to dst
|
||||
int sprite_width; ///< Real width of the sprite
|
||||
int sprite_height; ///< Real height of the sprite
|
||||
int left; ///< The left offset in the 'dst' in pixels to start drawing
|
||||
int top; ///< The top offset in the 'dst' in pixels to start drawing
|
||||
int skip_left; ///< How much pixels of the source to skip on the left (based on zoom of dst)
|
||||
int skip_top; ///< How much pixels of the source to skip on the top (based on zoom of dst)
|
||||
int width; ///< The width in pixels that needs to be drawn to dst
|
||||
int height; ///< The height in pixels that needs to be drawn to dst
|
||||
int sprite_width; ///< Real width of the sprite
|
||||
int sprite_height; ///< Real height of the sprite
|
||||
int left; ///< The left offset in the 'dst' in pixels to start drawing
|
||||
int top; ///< The top offset in the 'dst' in pixels to start drawing
|
||||
|
||||
void *dst; ///< Destination buffer
|
||||
int pitch; ///< The pitch of the destination buffer
|
||||
void *dst; ///< Destination buffer
|
||||
int pitch; ///< The pitch of the destination buffer
|
||||
};
|
||||
|
||||
/** Types of palette animation. */
|
||||
|
@ -202,11 +202,12 @@ public:
|
|||
/**
|
||||
* Post resize event
|
||||
*/
|
||||
virtual void PostResize() { };
|
||||
virtual void PostResize() {};
|
||||
|
||||
virtual ~Blitter() = default;
|
||||
|
||||
template <typename SetPixelT> void DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, int screen_height, int width, int dash, SetPixelT set_pixel);
|
||||
template <typename SetPixelT>
|
||||
void DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, int screen_height, int width, int dash, SetPixelT set_pixel);
|
||||
};
|
||||
|
||||
#endif /* BLITTER_BASE_HPP */
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
#ifndef BLITTER_COMMON_HPP
|
||||
#define BLITTER_COMMON_HPP
|
||||
|
||||
#include "base.hpp"
|
||||
#include "../core/math_func.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "../core/math_func.hpp"
|
||||
#include "base.hpp"
|
||||
|
||||
template <typename SetPixelT>
|
||||
void Blitter::DrawLineGeneric(int x1, int y1, int x2, int y2, int screen_width, int screen_height, int width, int dash, SetPixelT set_pixel)
|
||||
{
|
||||
|
@ -50,11 +50,11 @@ void Blitter::DrawLineGeneric(int x1, int y1, int x2, int y2, int screen_width,
|
|||
/* compute frac_diff = width * sqrt(dx*dx + dy*dy)
|
||||
* Start interval:
|
||||
* max(dx, dy) <= sqrt(dx*dx + dy*dy) <= sqrt(2) * max(dx, dy) <= 3/2 * max(dx, dy) */
|
||||
int64_t frac_sq = ((int64_t) width) * ((int64_t) width) * (((int64_t) dx) * ((int64_t) dx) + ((int64_t) dy) * ((int64_t) dy));
|
||||
int64_t frac_sq = ((int64_t)width) * ((int64_t)width) * (((int64_t)dx) * ((int64_t)dx) + ((int64_t)dy) * ((int64_t)dy));
|
||||
int frac_max = 3 * frac_diff / 2;
|
||||
while (frac_diff < frac_max) {
|
||||
int frac_test = (frac_diff + frac_max) / 2;
|
||||
if (((int64_t) frac_test) * ((int64_t) frac_test) < frac_sq) {
|
||||
if (((int64_t)frac_test) * ((int64_t)frac_test) < frac_sq) {
|
||||
frac_diff = frac_test + 1;
|
||||
} else {
|
||||
frac_max = frac_test - 1;
|
||||
|
@ -73,9 +73,9 @@ void Blitter::DrawLineGeneric(int x1, int y1, int x2, int y2, int screen_width,
|
|||
}
|
||||
if (x2 < 0 || x1 >= screen_width) return;
|
||||
|
||||
int y_low = y1;
|
||||
int y_high = y1;
|
||||
int frac_low = dy - frac_diff / 2;
|
||||
int y_low = y1;
|
||||
int y_high = y1;
|
||||
int frac_low = dy - frac_diff / 2;
|
||||
int frac_high = dy + frac_diff / 2;
|
||||
|
||||
while (frac_low < -(dx / 2)) {
|
||||
|
@ -90,7 +90,7 @@ void Blitter::DrawLineGeneric(int x1, int y1, int x2, int y2, int screen_width,
|
|||
if (x1 < 0) {
|
||||
dash_count = (-x1) % (dash + gap);
|
||||
auto adjust_frac = [&](int64_t frac, int &y_bound) -> int {
|
||||
frac -= ((int64_t) dy) * ((int64_t) x1);
|
||||
frac -= ((int64_t)dy) * ((int64_t)x1);
|
||||
if (frac >= 0) {
|
||||
int quotient = frac / dx;
|
||||
int remainder = frac % dx;
|
||||
|
@ -135,9 +135,9 @@ void Blitter::DrawLineGeneric(int x1, int y1, int x2, int y2, int screen_width,
|
|||
}
|
||||
if (y2 < 0 || y1 >= screen_height) return;
|
||||
|
||||
int x_low = x1;
|
||||
int x_high = x1;
|
||||
int frac_low = dx - frac_diff / 2;
|
||||
int x_low = x1;
|
||||
int x_high = x1;
|
||||
int frac_low = dx - frac_diff / 2;
|
||||
int frac_high = dx + frac_diff / 2;
|
||||
|
||||
while (frac_low < -(dy / 2)) {
|
||||
|
@ -152,7 +152,7 @@ void Blitter::DrawLineGeneric(int x1, int y1, int x2, int y2, int screen_width,
|
|||
if (y1 < 0) {
|
||||
dash_count = (-y1) % (dash + gap);
|
||||
auto adjust_frac = [&](int64_t frac, int &x_bound) -> int {
|
||||
frac -= ((int64_t) dx) * ((int64_t) y1);
|
||||
frac -= ((int64_t)dx) * ((int64_t)y1);
|
||||
if (frac >= 0) {
|
||||
int quotient = frac / dy;
|
||||
int remainder = frac % dy;
|
||||
|
|
|
@ -10,17 +10,16 @@
|
|||
#ifndef BLITTER_FACTORY_HPP
|
||||
#define BLITTER_FACTORY_HPP
|
||||
|
||||
#include "base.hpp"
|
||||
#include "../debug.h"
|
||||
#include "../string_func.h"
|
||||
|
||||
#include "base.hpp"
|
||||
|
||||
/**
|
||||
* The base factory, keeping track of all blitters.
|
||||
*/
|
||||
class BlitterFactory {
|
||||
private:
|
||||
const std::string name; ///< The name of the blitter factory.
|
||||
const std::string name; ///< The name of the blitter factory.
|
||||
const std::string description; ///< The description of the blitter.
|
||||
|
||||
typedef std::map<std::string, BlitterFactory *> Blitters; ///< Map of blitter factories.
|
||||
|
@ -55,8 +54,7 @@ protected:
|
|||
* @pre description != nullptr.
|
||||
* @pre There is no blitter registered with this name.
|
||||
*/
|
||||
BlitterFactory(const char *name, const char *description, bool usable = true) :
|
||||
name(name), description(description)
|
||||
BlitterFactory(const char *name, const char *description, bool usable = true) : name(name), description(description)
|
||||
{
|
||||
if (usable) {
|
||||
Blitters &blitters = GetBlitters();
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
/** @file null.cpp A blitter that doesn't blit. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "null.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
@ -21,7 +22,7 @@ Sprite *Blitter_Null::Encode(const SpriteLoader::SpriteCollection &sprite, Sprit
|
|||
dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite));
|
||||
|
||||
dest_sprite->height = sprite[ZOOM_LVL_MIN].height;
|
||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
||||
dest_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
|
||||
dest_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
|
||||
|
||||
|
|
|
@ -15,11 +15,20 @@
|
|||
/** Blitter that does nothing. */
|
||||
class Blitter_Null : public Blitter {
|
||||
public:
|
||||
uint8_t GetScreenDepth() override { return 0; }
|
||||
uint8_t GetScreenDepth() override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Draw(Blitter::BlitterParams *, BlitterMode, ZoomLevel) override {};
|
||||
void DrawColourMappingRect(void *, int, int, PaletteID) override {};
|
||||
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
|
||||
void *MoveTo(void *, int, int) override { return nullptr; };
|
||||
|
||||
void *MoveTo(void *, int, int) override
|
||||
{
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
void SetPixel(void *, int, int, uint8_t) override {};
|
||||
void DrawRect(void *, int, int, uint8_t) override {};
|
||||
void DrawLine(void *, int, int, int, int, int, int, uint8_t, int, int) override {};
|
||||
|
@ -27,18 +36,34 @@ public:
|
|||
void CopyToBuffer(const void *, void *, int, int) override {};
|
||||
void CopyImageToBuffer(const void *, void *, int, int, int) override {};
|
||||
void ScrollBuffer(void *, int &, int &, int &, int &, int, int) override {};
|
||||
size_t BufferSize(uint, uint) override { return 0; };
|
||||
void PaletteAnimate(const Palette &) override { };
|
||||
Blitter::PaletteAnimation UsePaletteAnimation() override { return Blitter::PaletteAnimation::None; };
|
||||
|
||||
std::string_view GetName() override { return "null"; }
|
||||
size_t BufferSize(uint, uint) override
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
|
||||
void PaletteAnimate(const Palette &) override {};
|
||||
|
||||
Blitter::PaletteAnimation UsePaletteAnimation() override
|
||||
{
|
||||
return Blitter::PaletteAnimation::None;
|
||||
};
|
||||
|
||||
std::string_view GetName() override
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
};
|
||||
|
||||
/** Factory for the blitter that does nothing. */
|
||||
class FBlitter_Null : public BlitterFactory {
|
||||
public:
|
||||
FBlitter_Null() : BlitterFactory("null", "Null Blitter (does nothing)") {}
|
||||
std::unique_ptr<Blitter> CreateInstance() override { return std::make_unique<Blitter_Null>(); }
|
||||
|
||||
std::unique_ptr<Blitter> CreateInstance() override
|
||||
{
|
||||
return std::make_unique<Blitter_Null>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* BLITTER_NULL_HPP */
|
||||
|
|
36
src/bmp.cpp
36
src/bmp.cpp
|
@ -8,9 +8,11 @@
|
|||
/** @file bmp.cpp Read and write support for bmps. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "random_access_file_type.h"
|
||||
|
||||
#include "bmp.h"
|
||||
|
||||
#include "core/bitmath_func.hpp"
|
||||
#include "random_access_file_type.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
@ -49,7 +51,7 @@ static inline bool BmpRead4(RandomAccessFile &file, BmpInfo &info, BmpData &data
|
|||
uint x = 0;
|
||||
uint8_t *pixel_row = &data.bitmap[(y - 1) * static_cast<size_t>(info.width)];
|
||||
while (x < info.width) {
|
||||
if (file.AtEndOfFile()) return false; // the file is shorter than expected
|
||||
if (file.AtEndOfFile()) return false; // the file is shorter than expected
|
||||
uint8_t b = file.ReadByte();
|
||||
*pixel_row++ = GB(b, 4, 4);
|
||||
x++;
|
||||
|
@ -229,7 +231,7 @@ static inline bool BmpRead24(RandomAccessFile &file, BmpInfo &info, BmpData &dat
|
|||
if (file.AtEndOfFile()) return false; // the file is shorter than expected
|
||||
*(pixel_row + 2) = file.ReadByte(); // green
|
||||
*(pixel_row + 1) = file.ReadByte(); // blue
|
||||
*pixel_row = file.ReadByte(); // red
|
||||
*pixel_row = file.ReadByte(); // red
|
||||
pixel_row += 3;
|
||||
}
|
||||
/* Padding for 32 bit align */
|
||||
|
@ -286,9 +288,9 @@ bool BmpReadHeader(RandomAccessFile &file, BmpInfo &info, BmpData &data)
|
|||
if (info.bpp <= 8) {
|
||||
/* Reads number of colours if available in info header */
|
||||
if (header_size >= 16) {
|
||||
file.SkipBytes(12); // skip image size and resolution
|
||||
file.SkipBytes(12); // skip image size and resolution
|
||||
info.palette_size = file.ReadDword(); // number of colours in palette
|
||||
file.SkipBytes(header_size - 16); // skip the end of info header
|
||||
file.SkipBytes(header_size - 16); // skip the end of info header
|
||||
}
|
||||
|
||||
uint maximum_palette_size = 1U << info.bpp;
|
||||
|
@ -323,16 +325,24 @@ bool BmpReadBitmap(RandomAccessFile &file, BmpInfo &info, BmpData &data)
|
|||
switch (info.compression) {
|
||||
case 0: // no compression
|
||||
switch (info.bpp) {
|
||||
case 1: return BmpRead1(file, info, data);
|
||||
case 4: return BmpRead4(file, info, data);
|
||||
case 8: return BmpRead8(file, info, data);
|
||||
case 24: return BmpRead24(file, info, data);
|
||||
default: NOT_REACHED();
|
||||
case 1:
|
||||
return BmpRead1(file, info, data);
|
||||
case 4:
|
||||
return BmpRead4(file, info, data);
|
||||
case 8:
|
||||
return BmpRead8(file, info, data);
|
||||
case 24:
|
||||
return BmpRead24(file, info, data);
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: return BmpRead8Rle(file, info, data); // 8-bit RLE compression
|
||||
case 2: return BmpRead4Rle(file, info, data); // 4-bit RLE compression
|
||||
default: NOT_REACHED();
|
||||
case 1:
|
||||
return BmpRead8Rle(file, info, data); // 8-bit RLE compression
|
||||
case 2:
|
||||
return BmpRead4Rle(file, info, data); // 4-bit RLE compression
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
|
10
src/bmp.h
10
src/bmp.h
|
@ -15,11 +15,11 @@
|
|||
|
||||
struct BmpInfo {
|
||||
size_t offset; ///< offset of bitmap data from .bmp file beginning
|
||||
uint32_t width; ///< bitmap width
|
||||
uint32_t height; ///< bitmap height
|
||||
bool os2_bmp; ///< true if OS/2 1.x or windows 2.x bitmap
|
||||
uint16_t bpp; ///< bits per pixel
|
||||
uint32_t compression; ///< compression method (0 = none, 1 = 8-bit RLE, 2 = 4-bit RLE)
|
||||
uint32_t width; ///< bitmap width
|
||||
uint32_t height; ///< bitmap height
|
||||
bool os2_bmp; ///< true if OS/2 1.x or windows 2.x bitmap
|
||||
uint16_t bpp; ///< bits per pixel
|
||||
uint32_t compression; ///< compression method (0 = none, 1 = 8-bit RLE, 2 = 4-bit RLE)
|
||||
uint32_t palette_size; ///< number of colours in palette
|
||||
};
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
/** @file bootstrap_gui.cpp Barely used user interface for bootstrapping OpenTTD, i.e. downloading the required content. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "base_media_base.h"
|
||||
#include "base_media_graphics.h"
|
||||
#include "blitter/factory.hpp"
|
||||
|
@ -15,22 +16,21 @@
|
|||
|
||||
#if defined(WITH_FREETYPE) || defined(WITH_UNISCRIBE) || defined(WITH_COCOA)
|
||||
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "error.h"
|
||||
#include "fontcache.h"
|
||||
#include "gfx_func.h"
|
||||
#include "network/network.h"
|
||||
#include "network/network_content_gui.h"
|
||||
#include "openttd.h"
|
||||
#include "strings_func.h"
|
||||
#include "video/video_driver.hpp"
|
||||
#include "window_func.h"
|
||||
# include "core/geometry_func.hpp"
|
||||
# include "error.h"
|
||||
# include "fontcache.h"
|
||||
# include "gfx_func.h"
|
||||
# include "network/network.h"
|
||||
# include "network/network_content_gui.h"
|
||||
# include "openttd.h"
|
||||
# include "strings_func.h"
|
||||
# include "video/video_driver.hpp"
|
||||
# include "window_func.h"
|
||||
|
||||
#include "widgets/bootstrap_widget.h"
|
||||
# include "widgets/bootstrap_widget.h"
|
||||
# include "table/strings.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
# include "safeguards.h"
|
||||
|
||||
/** Widgets for the background window to prevent smearing. */
|
||||
/* clang-format off */
|
||||
|
@ -43,12 +43,7 @@ static constexpr NWidgetPart _background_widgets[] = {
|
|||
/**
|
||||
* Window description for the background window to prevent smearing.
|
||||
*/
|
||||
static WindowDesc _background_desc(
|
||||
WDP_MANUAL, nullptr, 0, 0,
|
||||
WC_BOOTSTRAP, WC_NONE,
|
||||
WindowDefaultFlag::NoClose,
|
||||
_background_widgets
|
||||
);
|
||||
static WindowDesc _background_desc(WDP_MANUAL, nullptr, 0, 0, WC_BOOTSTRAP, WC_NONE, WindowDefaultFlag::NoClose, _background_widgets);
|
||||
|
||||
/** The background for the game. */
|
||||
class BootstrapBackground : public Window {
|
||||
|
@ -81,12 +76,7 @@ static constexpr NWidgetPart _nested_bootstrap_errmsg_widgets[] = {
|
|||
/* clang-format on */
|
||||
|
||||
/** Window description for the error window. */
|
||||
static WindowDesc _bootstrap_errmsg_desc(
|
||||
WDP_CENTER, nullptr, 0, 0,
|
||||
WC_BOOTSTRAP, WC_NONE,
|
||||
{WindowDefaultFlag::Modal, WindowDefaultFlag::NoClose},
|
||||
_nested_bootstrap_errmsg_widgets
|
||||
);
|
||||
static WindowDesc _bootstrap_errmsg_desc(WDP_CENTER, nullptr, 0, 0, WC_BOOTSTRAP, WC_NONE, {WindowDefaultFlag::Modal, WindowDefaultFlag::NoClose}, _nested_bootstrap_errmsg_widgets);
|
||||
|
||||
/** The window for a failed bootstrap. */
|
||||
class BootstrapErrorWindow : public Window {
|
||||
|
@ -141,20 +131,13 @@ static constexpr NWidgetPart _nested_bootstrap_download_status_window_widgets[]
|
|||
|
||||
/** Window description for the download window */
|
||||
static WindowDesc _bootstrap_download_status_window_desc(
|
||||
WDP_CENTER, nullptr, 0, 0,
|
||||
WC_NETWORK_STATUS_WINDOW, WC_NONE,
|
||||
{WindowDefaultFlag::Modal, WindowDefaultFlag::NoClose},
|
||||
_nested_bootstrap_download_status_window_widgets
|
||||
);
|
||||
|
||||
WDP_CENTER, nullptr, 0, 0, WC_NETWORK_STATUS_WINDOW, WC_NONE, {WindowDefaultFlag::Modal, WindowDefaultFlag::NoClose}, _nested_bootstrap_download_status_window_widgets);
|
||||
|
||||
/** Window for showing the download status of content */
|
||||
struct BootstrapContentDownloadStatusWindow : public BaseNetworkContentDownloadStatusWindow {
|
||||
public:
|
||||
/** Simple call the constructor of the superclass. */
|
||||
BootstrapContentDownloadStatusWindow() : BaseNetworkContentDownloadStatusWindow(_bootstrap_download_status_window_desc)
|
||||
{
|
||||
}
|
||||
BootstrapContentDownloadStatusWindow() : BaseNetworkContentDownloadStatusWindow(_bootstrap_download_status_window_desc) {}
|
||||
|
||||
void Close([[maybe_unused]] int data = 0) override
|
||||
{
|
||||
|
@ -194,12 +177,7 @@ static constexpr NWidgetPart _bootstrap_query_widgets[] = {
|
|||
/* clang-format on */
|
||||
|
||||
/** The window description for the query. */
|
||||
static WindowDesc _bootstrap_query_desc(
|
||||
WDP_CENTER, nullptr, 0, 0,
|
||||
WC_CONFIRM_POPUP_QUERY, WC_NONE,
|
||||
WindowDefaultFlag::NoClose,
|
||||
_bootstrap_query_widgets
|
||||
);
|
||||
static WindowDesc _bootstrap_query_desc(WDP_CENTER, nullptr, 0, 0, WC_CONFIRM_POPUP_QUERY, WC_NONE, WindowDefaultFlag::NoClose, _bootstrap_query_widgets);
|
||||
|
||||
/** The window for the query. It can't use the generic query window as that uses sprites that don't exist yet. */
|
||||
class BootstrapAskForDownloadWindow : public Window, ContentCallback {
|
||||
|
@ -320,7 +298,9 @@ public:
|
|||
void OnConnect(bool success) override
|
||||
{
|
||||
if (!success) {
|
||||
EM_ASM({ if (window["openttd_bootstrap_failed"]) openttd_bootstrap_failed(); });
|
||||
EM_ASM({
|
||||
if (window["openttd_bootstrap_failed"]) openttd_bootstrap_failed();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -337,7 +317,11 @@ public:
|
|||
_network_content_client.DownloadSelectedContent(this->total_files, this->total_bytes);
|
||||
this->downloading = true;
|
||||
|
||||
EM_ASM({ if (window["openttd_bootstrap"]) openttd_bootstrap($0, $1); }, this->downloaded_bytes, this->total_bytes);
|
||||
EM_ASM(
|
||||
{
|
||||
if (window["openttd_bootstrap"]) openttd_bootstrap($0, $1);
|
||||
},
|
||||
this->downloaded_bytes, this->total_bytes);
|
||||
}
|
||||
|
||||
void OnDownloadProgress(const ContentInfo &, int bytes) override
|
||||
|
@ -349,7 +333,11 @@ public:
|
|||
this->downloaded_bytes += bytes;
|
||||
}
|
||||
|
||||
EM_ASM({ if (window["openttd_bootstrap"]) openttd_bootstrap($0, $1); }, this->downloaded_bytes, this->total_bytes);
|
||||
EM_ASM(
|
||||
{
|
||||
if (window["openttd_bootstrap"]) openttd_bootstrap($0, $1);
|
||||
},
|
||||
this->downloaded_bytes, this->total_bytes);
|
||||
}
|
||||
|
||||
void OnDownloadComplete(ContentID) override
|
||||
|
@ -382,9 +370,9 @@ bool HandleBootstrap()
|
|||
/* First tell the game we're bootstrapping. */
|
||||
_game_mode = GM_BOOTSTRAP;
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
# if defined(__EMSCRIPTEN__)
|
||||
new BootstrapEmscripten();
|
||||
#else
|
||||
# else
|
||||
/* Initialise the font cache. */
|
||||
InitializeUnicodeGlyphMap();
|
||||
/* Next "force" finding a suitable non-sprite font as the local font is missing. */
|
||||
|
@ -393,7 +381,7 @@ bool HandleBootstrap()
|
|||
/* Initialise the palette. The biggest step is 'faking' some recolour sprites.
|
||||
* This way the mauve and gray colours work and we can show the user interface. */
|
||||
GfxInitPalettes();
|
||||
static const int offsets[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0x04, 0x08 };
|
||||
static const int offsets[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0x04, 0x08};
|
||||
for (Colours i = COLOUR_BEGIN; i != COLOUR_END; i++) {
|
||||
for (ColourShade j = SHADE_BEGIN; j < SHADE_END; j++) {
|
||||
SetColourGradient(i, j, offsets[i] + j);
|
||||
|
@ -403,7 +391,7 @@ bool HandleBootstrap()
|
|||
/* Finally ask the question. */
|
||||
new BootstrapBackground();
|
||||
new BootstrapAskForDownloadWindow();
|
||||
#endif /* __EMSCRIPTEN__ */
|
||||
# endif /* __EMSCRIPTEN__ */
|
||||
|
||||
/* Process the user events. */
|
||||
VideoDriver::GetInstance()->MainLoop();
|
||||
|
|
18
src/bridge.h
18
src/bridge.h
|
@ -42,16 +42,16 @@ typedef uint BridgeType; ///< Bridge spec number.
|
|||
*/
|
||||
struct BridgeSpec {
|
||||
TimerGameCalendar::Year avail_year; ///< the year where it becomes available
|
||||
uint8_t min_length; ///< the minimum length (not counting start and end tile)
|
||||
uint16_t max_length; ///< the maximum length (not counting start and end tile)
|
||||
uint16_t price; ///< the price multiplier
|
||||
uint16_t speed; ///< maximum travel speed (1 unit = 1/1.6 mph = 1 km-ish/h)
|
||||
SpriteID sprite; ///< the sprite which is used in the GUI
|
||||
PaletteID pal; ///< the palette which is used in the GUI
|
||||
StringID material; ///< the string that contains the bridge description
|
||||
StringID transport_name[2]; ///< description of the bridge, when built for road or rail
|
||||
uint8_t min_length; ///< the minimum length (not counting start and end tile)
|
||||
uint16_t max_length; ///< the maximum length (not counting start and end tile)
|
||||
uint16_t price; ///< the price multiplier
|
||||
uint16_t speed; ///< maximum travel speed (1 unit = 1/1.6 mph = 1 km-ish/h)
|
||||
SpriteID sprite; ///< the sprite which is used in the GUI
|
||||
PaletteID pal; ///< the palette which is used in the GUI
|
||||
StringID material; ///< the string that contains the bridge description
|
||||
StringID transport_name[2]; ///< description of the bridge, when built for road or rail
|
||||
std::vector<std::vector<PalSpriteID>> sprite_table; ///< table of sprites for drawing the bridge
|
||||
uint8_t flags; ///< bit 0 set: disable drawing of far pillars.
|
||||
uint8_t flags; ///< bit 0 set: disable drawing of far pillars.
|
||||
};
|
||||
|
||||
extern BridgeSpec _bridge[MAX_BRIDGES];
|
||||
|
|
|
@ -8,24 +8,24 @@
|
|||
/** @file bridge_gui.cpp Graphical user interface for bridge construction */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "command_func.h"
|
||||
#include "dropdown_func.h"
|
||||
#include "error.h"
|
||||
#include "gfx_func.h"
|
||||
#include "rail.h"
|
||||
#include "road.h"
|
||||
#include "strings_func.h"
|
||||
#include "window_func.h"
|
||||
#include "sound_func.h"
|
||||
#include "gfx_func.h"
|
||||
#include "tunnelbridge.h"
|
||||
#include "sortlist_type.h"
|
||||
#include "dropdown_func.h"
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "tunnelbridge_map.h"
|
||||
#include "road_gui.h"
|
||||
#include "sortlist_type.h"
|
||||
#include "sound_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "tunnelbridge.h"
|
||||
#include "tunnelbridge_cmd.h"
|
||||
#include "tunnelbridge_map.h"
|
||||
#include "window_func.h"
|
||||
|
||||
#include "widgets/bridge_widget.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
@ -80,7 +80,7 @@ private:
|
|||
STR_SORT_BY_COST,
|
||||
STR_SORT_BY_MAX_SPEED,
|
||||
};
|
||||
static const std::initializer_list<GUIBridgeList::SortFunction * const> sorter_funcs;
|
||||
static const std::initializer_list<GUIBridgeList::SortFunction *const> sorter_funcs;
|
||||
|
||||
/* Internal variables */
|
||||
TileIndex start_tile = INVALID_TILE;
|
||||
|
@ -112,12 +112,16 @@ private:
|
|||
void BuildBridge(BridgeType type)
|
||||
{
|
||||
switch (this->transport_type) {
|
||||
case TRANSPORT_RAIL: _last_railbridge_type = type; break;
|
||||
case TRANSPORT_ROAD: _last_roadbridge_type = type; break;
|
||||
default: break;
|
||||
case TRANSPORT_RAIL:
|
||||
_last_railbridge_type = type;
|
||||
break;
|
||||
case TRANSPORT_ROAD:
|
||||
_last_roadbridge_type = type;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Command<CMD_BUILD_BRIDGE>::Post(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, CcBuildBridge,
|
||||
this->end_tile, this->start_tile, this->transport_type, type, this->road_rail_type);
|
||||
Command<CMD_BUILD_BRIDGE>::Post(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, CcBuildBridge, this->end_tile, this->start_tile, this->transport_type, type, this->road_rail_type);
|
||||
}
|
||||
|
||||
/** Sort the builable bridges */
|
||||
|
@ -142,24 +146,18 @@ private:
|
|||
{
|
||||
/* If the bridge has no meaningful speed limit, don't display it. */
|
||||
if (bridge_data.spec->speed == UINT16_MAX) {
|
||||
return _game_mode == GM_EDITOR
|
||||
? GetString(STR_SELECT_BRIDGE_INFO_NAME, bridge_data.spec->material)
|
||||
: GetString(STR_SELECT_BRIDGE_INFO_NAME_COST, bridge_data.spec->material, bridge_data.cost);
|
||||
return _game_mode == GM_EDITOR ? GetString(STR_SELECT_BRIDGE_INFO_NAME, bridge_data.spec->material) :
|
||||
GetString(STR_SELECT_BRIDGE_INFO_NAME_COST, bridge_data.spec->material, bridge_data.cost);
|
||||
}
|
||||
|
||||
uint64_t packed_velocity = PackVelocity(bridge_data.spec->speed, static_cast<VehicleType>(this->transport_type));
|
||||
return _game_mode == GM_EDITOR
|
||||
? GetString(STR_SELECT_BRIDGE_INFO_NAME_MAX_SPEED, bridge_data.spec->material, packed_velocity)
|
||||
: GetString(STR_SELECT_BRIDGE_INFO_NAME_MAX_SPEED_COST, bridge_data.spec->material, packed_velocity, bridge_data.cost);
|
||||
return _game_mode == GM_EDITOR ? GetString(STR_SELECT_BRIDGE_INFO_NAME_MAX_SPEED, bridge_data.spec->material, packed_velocity) :
|
||||
GetString(STR_SELECT_BRIDGE_INFO_NAME_MAX_SPEED_COST, bridge_data.spec->material, packed_velocity, bridge_data.cost);
|
||||
}
|
||||
|
||||
public:
|
||||
BuildBridgeWindow(WindowDesc &desc, TileIndex start, TileIndex end, TransportType transport_type, uint8_t road_rail_type, GUIBridgeList &&bl) : Window(desc),
|
||||
start_tile(start),
|
||||
end_tile(end),
|
||||
transport_type(transport_type),
|
||||
road_rail_type(road_rail_type),
|
||||
bridges(std::move(bl))
|
||||
BuildBridgeWindow(WindowDesc &desc, TileIndex start, TileIndex end, TransportType transport_type, uint8_t road_rail_type, GUIBridgeList &&bl) :
|
||||
Window(desc), start_tile(start), end_tile(end), transport_type(transport_type), road_rail_type(road_rail_type), bridges(std::move(bl))
|
||||
{
|
||||
this->CreateNestedTree();
|
||||
this->vscroll = this->GetScrollbar(WID_BBS_SCROLLBAR);
|
||||
|
@ -200,7 +198,7 @@ public:
|
|||
}
|
||||
case WID_BBS_BRIDGE_LIST: {
|
||||
Dimension sprite_dim = {0, 0}; // Biggest bridge sprite dimension
|
||||
Dimension text_dim = {0, 0}; // Biggest text dimension
|
||||
Dimension text_dim = {0, 0}; // Biggest text dimension
|
||||
for (const BuildBridgeData &bridge_data : this->bridges) {
|
||||
sprite_dim = maxdim(sprite_dim, GetScaledSpriteSize(bridge_data.spec->sprite));
|
||||
text_dim = maxdim(text_dim, GetStringBoundingBox(GetBridgeSelectString(bridge_data)));
|
||||
|
@ -262,7 +260,8 @@ public:
|
|||
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
|
||||
{
|
||||
switch (widget) {
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
case WID_BBS_BRIDGE_LIST: {
|
||||
auto it = this->vscroll->GetScrolledItemFromWidget(this->bridges, pt.y, this, WID_BBS_BRIDGE_LIST);
|
||||
if (it != this->bridges.end()) {
|
||||
|
@ -302,11 +301,7 @@ public:
|
|||
Listing BuildBridgeWindow::last_sorting = {true, 2};
|
||||
|
||||
/** Available bridge sorting functions. */
|
||||
const std::initializer_list<GUIBridgeList::SortFunction * const> BuildBridgeWindow::sorter_funcs = {
|
||||
&BridgeIndexSorter,
|
||||
&BridgePriceSorter,
|
||||
&BridgeSpeedSorter
|
||||
};
|
||||
const std::initializer_list<GUIBridgeList::SortFunction *const> BuildBridgeWindow::sorter_funcs = {&BridgeIndexSorter, &BridgePriceSorter, &BridgeSpeedSorter};
|
||||
|
||||
/** Widgets of the bridge gui. */
|
||||
/* clang-format off */
|
||||
|
@ -339,12 +334,7 @@ static constexpr NWidgetPart _nested_build_bridge_widgets[] = {
|
|||
/* clang-format on */
|
||||
|
||||
/** Window definition for the rail bridge selection window. */
|
||||
static WindowDesc _build_bridge_desc(
|
||||
WDP_AUTO, "build_bridge", 200, 114,
|
||||
WC_BUILD_BRIDGE, WC_BUILD_TOOLBAR,
|
||||
WindowDefaultFlag::Construction,
|
||||
_nested_build_bridge_widgets
|
||||
);
|
||||
static WindowDesc _build_bridge_desc(WDP_AUTO, "build_bridge", 200, 114, WC_BUILD_BRIDGE, WC_BUILD_TOOLBAR, WindowDefaultFlag::Construction, _nested_build_bridge_widgets);
|
||||
|
||||
/**
|
||||
* Prepare the data for the build a bridge window.
|
||||
|
@ -370,9 +360,14 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
|
|||
*/
|
||||
BridgeType last_bridge_type = 0;
|
||||
switch (transport_type) {
|
||||
case TRANSPORT_ROAD: last_bridge_type = _last_roadbridge_type; break;
|
||||
case TRANSPORT_RAIL: last_bridge_type = _last_railbridge_type; break;
|
||||
default: break; // water ways and air routes don't have bridge types
|
||||
case TRANSPORT_ROAD:
|
||||
last_bridge_type = _last_roadbridge_type;
|
||||
break;
|
||||
case TRANSPORT_RAIL:
|
||||
last_bridge_type = _last_railbridge_type;
|
||||
break;
|
||||
default:
|
||||
break; // water ways and air routes don't have bridge types
|
||||
}
|
||||
if (_ctrl_pressed && CheckBridgeAvailability(last_bridge_type, bridge_len).Succeeded()) {
|
||||
Command<CMD_BUILD_BRIDGE>::Post(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, CcBuildBridge, end, start, transport_type, last_bridge_type, road_rail_type);
|
||||
|
@ -412,8 +407,11 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
|
|||
|
||||
break;
|
||||
}
|
||||
case TRANSPORT_RAIL: infra_cost = (bridge_len + 2) * RailBuildCost((RailType)road_rail_type); break;
|
||||
default: break;
|
||||
case TRANSPORT_RAIL:
|
||||
infra_cost = (bridge_len + 2) * RailBuildCost((RailType)road_rail_type);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bool any_available = false;
|
||||
|
@ -433,8 +431,7 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
|
|||
}
|
||||
}
|
||||
/* give error cause if no bridges available here*/
|
||||
if (!any_available)
|
||||
{
|
||||
if (!any_available) {
|
||||
errmsg = type_check.GetErrorMessage();
|
||||
}
|
||||
}
|
||||
|
@ -442,7 +439,6 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
|
|||
if (!bl.empty()) {
|
||||
new BuildBridgeWindow(_build_bridge_desc, start, end, transport_type, road_rail_type, std::move(bl));
|
||||
} else {
|
||||
ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE), GetEncodedString(errmsg),
|
||||
WL_INFO, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE);
|
||||
ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE), GetEncodedString(errmsg), WL_INFO, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
/** @file bridge_map.cpp Map accessor functions for bridges. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "landscape.h"
|
||||
#include "tunnelbridge_map.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
||||
/**
|
||||
* Finds the end of a bridge in the specified direction starting at a middle tile
|
||||
* @param tile the bridge tile to find the bridge ramp for
|
||||
|
@ -31,7 +31,6 @@ static TileIndex GetBridgeEnd(TileIndex tile, DiagDirection dir)
|
|||
return tile;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds the northern end of a bridge starting at a middle tile
|
||||
* @param t the bridge tile to find the bridge ramp for
|
||||
|
@ -41,7 +40,6 @@ TileIndex GetNorthernBridgeEnd(TileIndex t)
|
|||
return GetBridgeEnd(t, ReverseDiagDir(AxisToDiagDir(GetBridgeAxis(t))));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds the southern end of a bridge starting at a middle tile
|
||||
* @param t the bridge tile to find the bridge ramp for
|
||||
|
@ -51,7 +49,6 @@ TileIndex GetSouthernBridgeEnd(TileIndex t)
|
|||
return GetBridgeEnd(t, AxisToDiagDir(GetBridgeAxis(t)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Starting at one bridge end finds the other bridge end
|
||||
* @param tile the bridge ramp tile to find the other bridge ramp for
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
#ifndef BRIDGE_MAP_H
|
||||
#define BRIDGE_MAP_H
|
||||
|
||||
#include "bridge.h"
|
||||
#include "rail_map.h"
|
||||
#include "road_map.h"
|
||||
#include "bridge.h"
|
||||
#include "water_map.h"
|
||||
|
||||
/**
|
||||
|
@ -76,6 +76,7 @@ TileIndex GetSouthernBridgeEnd(TileIndex t);
|
|||
TileIndex GetOtherBridgeEnd(TileIndex t);
|
||||
|
||||
int GetBridgeHeight(TileIndex tile);
|
||||
|
||||
/**
|
||||
* Get the height ('z') of a bridge in pixels.
|
||||
* @param tile the bridge ramp tile to get the bridge height from
|
||||
|
|
|
@ -8,41 +8,41 @@
|
|||
/** @file build_vehicle_gui.cpp GUI for building vehicles. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "engine_base.h"
|
||||
#include "engine_func.h"
|
||||
#include "station_base.h"
|
||||
#include "network/network.h"
|
||||
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "articulated_vehicles.h"
|
||||
#include "textbuf_gui.h"
|
||||
#include "autoreplace_func.h"
|
||||
#include "cargotype.h"
|
||||
#include "command_func.h"
|
||||
#include "company_func.h"
|
||||
#include "vehicle_gui.h"
|
||||
#include "dropdown_func.h"
|
||||
#include "dropdown_type.h"
|
||||
#include "engine_base.h"
|
||||
#include "engine_cmd.h"
|
||||
#include "engine_func.h"
|
||||
#include "engine_gui.h"
|
||||
#include "group.h"
|
||||
#include "hotkeys.h"
|
||||
#include "network/network.h"
|
||||
#include "newgrf_badge.h"
|
||||
#include "newgrf_badge_gui.h"
|
||||
#include "newgrf_engine.h"
|
||||
#include "newgrf_text.h"
|
||||
#include "group.h"
|
||||
#include "querystring_gui.h"
|
||||
#include "station_base.h"
|
||||
#include "string_func.h"
|
||||
#include "stringfilter_type.h"
|
||||
#include "strings_func.h"
|
||||
#include "window_func.h"
|
||||
#include "textbuf_gui.h"
|
||||
#include "timer/timer_game_calendar.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "dropdown_type.h"
|
||||
#include "dropdown_func.h"
|
||||
#include "engine_gui.h"
|
||||
#include "cargotype.h"
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "autoreplace_func.h"
|
||||
#include "engine_cmd.h"
|
||||
#include "train_cmd.h"
|
||||
#include "vehicle_cmd.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "vehicle_gui.h"
|
||||
#include "window_func.h"
|
||||
#include "zoom_func.h"
|
||||
#include "querystring_gui.h"
|
||||
#include "stringfilter_type.h"
|
||||
#include "hotkeys.h"
|
||||
|
||||
#include "widgets/build_vehicle_widget.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
@ -98,12 +98,12 @@ static constexpr NWidgetPart _nested_build_vehicle_widgets[] = {
|
|||
};
|
||||
/* clang-format on */
|
||||
|
||||
|
||||
bool _engine_sort_direction; ///< \c false = descending, \c true = ascending.
|
||||
uint8_t _engine_sort_last_criteria[] = {0, 0, 0, 0}; ///< Last set sort criteria, for each vehicle type.
|
||||
bool _engine_sort_last_order[] = {false, false, false, false}; ///< Last set direction of the sort order, for each vehicle type.
|
||||
uint8_t _engine_sort_last_criteria[] = {0, 0, 0, 0}; ///< Last set sort criteria, for each vehicle type.
|
||||
bool _engine_sort_last_order[] = {false, false, false, false}; ///< Last set direction of the sort order, for each vehicle type.
|
||||
bool _engine_sort_show_hidden_engines[] = {false, false, false, false}; ///< Last set 'show hidden engines' setting for each vehicle type.
|
||||
static CargoType _engine_sort_last_cargo_criteria[] = {CargoFilterCriteria::CF_ANY, CargoFilterCriteria::CF_ANY, CargoFilterCriteria::CF_ANY, CargoFilterCriteria::CF_ANY}; ///< Last set filter criteria, for each vehicle type.
|
||||
static CargoType _engine_sort_last_cargo_criteria[] = {
|
||||
CargoFilterCriteria::CF_ANY, CargoFilterCriteria::CF_ANY, CargoFilterCriteria::CF_ANY, CargoFilterCriteria::CF_ANY}; ///< Last set filter criteria, for each vehicle type.
|
||||
|
||||
/**
|
||||
* Determines order of engines by engineID
|
||||
|
@ -136,7 +136,7 @@ static bool EngineIntroDateSorter(const GUIEngineListItem &a, const GUIEngineLis
|
|||
}
|
||||
|
||||
/* cached values for EngineNameSorter to spare many GetString() calls */
|
||||
static EngineID _last_engine[2] = { EngineID::Invalid(), EngineID::Invalid() };
|
||||
static EngineID _last_engine[2] = {EngineID::Invalid(), EngineID::Invalid()};
|
||||
|
||||
/**
|
||||
* Determines order of engines by name
|
||||
|
@ -146,7 +146,7 @@ static EngineID _last_engine[2] = { EngineID::Invalid(), EngineID::Invalid() };
|
|||
*/
|
||||
static bool EngineNameSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
|
||||
{
|
||||
static std::string last_name[2] = { {}, {} };
|
||||
static std::string last_name[2] = {{}, {}};
|
||||
|
||||
if (a.engine_id != _last_engine[0]) {
|
||||
_last_engine[0] = a.engine_id;
|
||||
|
@ -303,7 +303,7 @@ static bool EnginePowerVsRunningCostSorter(const GUIEngineListItem &a, const GUI
|
|||
* Also if both have no power then sort with reverse of running cost to simulate
|
||||
* previous sorting behaviour for wagons. */
|
||||
if (v_a == 0 && v_b == 0) return EngineRunningCostSorter(b, a);
|
||||
if (v_a == v_b) return EngineNumberSorter(a, b);
|
||||
if (v_a == v_b) return EngineNumberSorter(a, b);
|
||||
return _engine_sort_direction != (v_a < v_b);
|
||||
}
|
||||
|
||||
|
@ -436,104 +436,110 @@ static bool AircraftRangeSorter(const GUIEngineListItem &a, const GUIEngineListI
|
|||
}
|
||||
|
||||
/** Sort functions for the vehicle sort criteria, for each vehicle type. */
|
||||
EngList_SortTypeFunction * const _engine_sort_functions[][11] = {{
|
||||
/* Trains */
|
||||
&EngineNumberSorter,
|
||||
&EngineCostSorter,
|
||||
&EngineSpeedSorter,
|
||||
&EnginePowerSorter,
|
||||
&EngineTractiveEffortSorter,
|
||||
&EngineIntroDateSorter,
|
||||
&EngineNameSorter,
|
||||
&EngineRunningCostSorter,
|
||||
&EnginePowerVsRunningCostSorter,
|
||||
&EngineReliabilitySorter,
|
||||
&TrainEngineCapacitySorter,
|
||||
}, {
|
||||
/* Road vehicles */
|
||||
&EngineNumberSorter,
|
||||
&EngineCostSorter,
|
||||
&EngineSpeedSorter,
|
||||
&EnginePowerSorter,
|
||||
&EngineTractiveEffortSorter,
|
||||
&EngineIntroDateSorter,
|
||||
&EngineNameSorter,
|
||||
&EngineRunningCostSorter,
|
||||
&EnginePowerVsRunningCostSorter,
|
||||
&EngineReliabilitySorter,
|
||||
&RoadVehEngineCapacitySorter,
|
||||
}, {
|
||||
/* Ships */
|
||||
&EngineNumberSorter,
|
||||
&EngineCostSorter,
|
||||
&EngineSpeedSorter,
|
||||
&EngineIntroDateSorter,
|
||||
&EngineNameSorter,
|
||||
&EngineRunningCostSorter,
|
||||
&EngineReliabilitySorter,
|
||||
&ShipEngineCapacitySorter,
|
||||
}, {
|
||||
/* Aircraft */
|
||||
&EngineNumberSorter,
|
||||
&EngineCostSorter,
|
||||
&EngineSpeedSorter,
|
||||
&EngineIntroDateSorter,
|
||||
&EngineNameSorter,
|
||||
&EngineRunningCostSorter,
|
||||
&EngineReliabilitySorter,
|
||||
&AircraftEngineCargoSorter,
|
||||
&AircraftRangeSorter,
|
||||
}};
|
||||
EngList_SortTypeFunction *const _engine_sort_functions[][11] = {{
|
||||
/* Trains */
|
||||
&EngineNumberSorter,
|
||||
&EngineCostSorter,
|
||||
&EngineSpeedSorter,
|
||||
&EnginePowerSorter,
|
||||
&EngineTractiveEffortSorter,
|
||||
&EngineIntroDateSorter,
|
||||
&EngineNameSorter,
|
||||
&EngineRunningCostSorter,
|
||||
&EnginePowerVsRunningCostSorter,
|
||||
&EngineReliabilitySorter,
|
||||
&TrainEngineCapacitySorter,
|
||||
},
|
||||
{
|
||||
/* Road vehicles */
|
||||
&EngineNumberSorter,
|
||||
&EngineCostSorter,
|
||||
&EngineSpeedSorter,
|
||||
&EnginePowerSorter,
|
||||
&EngineTractiveEffortSorter,
|
||||
&EngineIntroDateSorter,
|
||||
&EngineNameSorter,
|
||||
&EngineRunningCostSorter,
|
||||
&EnginePowerVsRunningCostSorter,
|
||||
&EngineReliabilitySorter,
|
||||
&RoadVehEngineCapacitySorter,
|
||||
},
|
||||
{
|
||||
/* Ships */
|
||||
&EngineNumberSorter,
|
||||
&EngineCostSorter,
|
||||
&EngineSpeedSorter,
|
||||
&EngineIntroDateSorter,
|
||||
&EngineNameSorter,
|
||||
&EngineRunningCostSorter,
|
||||
&EngineReliabilitySorter,
|
||||
&ShipEngineCapacitySorter,
|
||||
},
|
||||
{
|
||||
/* Aircraft */
|
||||
&EngineNumberSorter,
|
||||
&EngineCostSorter,
|
||||
&EngineSpeedSorter,
|
||||
&EngineIntroDateSorter,
|
||||
&EngineNameSorter,
|
||||
&EngineRunningCostSorter,
|
||||
&EngineReliabilitySorter,
|
||||
&AircraftEngineCargoSorter,
|
||||
&AircraftRangeSorter,
|
||||
}};
|
||||
|
||||
/** Dropdown menu strings for the vehicle sort criteria. */
|
||||
const std::initializer_list<const StringID> _engine_sort_listing[] = {{
|
||||
/* Trains */
|
||||
STR_SORT_BY_ENGINE_ID,
|
||||
STR_SORT_BY_COST,
|
||||
STR_SORT_BY_MAX_SPEED,
|
||||
STR_SORT_BY_POWER,
|
||||
STR_SORT_BY_TRACTIVE_EFFORT,
|
||||
STR_SORT_BY_INTRO_DATE,
|
||||
STR_SORT_BY_NAME,
|
||||
STR_SORT_BY_RUNNING_COST,
|
||||
STR_SORT_BY_POWER_VS_RUNNING_COST,
|
||||
STR_SORT_BY_RELIABILITY,
|
||||
STR_SORT_BY_CARGO_CAPACITY,
|
||||
}, {
|
||||
/* Road vehicles */
|
||||
STR_SORT_BY_ENGINE_ID,
|
||||
STR_SORT_BY_COST,
|
||||
STR_SORT_BY_MAX_SPEED,
|
||||
STR_SORT_BY_POWER,
|
||||
STR_SORT_BY_TRACTIVE_EFFORT,
|
||||
STR_SORT_BY_INTRO_DATE,
|
||||
STR_SORT_BY_NAME,
|
||||
STR_SORT_BY_RUNNING_COST,
|
||||
STR_SORT_BY_POWER_VS_RUNNING_COST,
|
||||
STR_SORT_BY_RELIABILITY,
|
||||
STR_SORT_BY_CARGO_CAPACITY,
|
||||
}, {
|
||||
/* Ships */
|
||||
STR_SORT_BY_ENGINE_ID,
|
||||
STR_SORT_BY_COST,
|
||||
STR_SORT_BY_MAX_SPEED,
|
||||
STR_SORT_BY_INTRO_DATE,
|
||||
STR_SORT_BY_NAME,
|
||||
STR_SORT_BY_RUNNING_COST,
|
||||
STR_SORT_BY_RELIABILITY,
|
||||
STR_SORT_BY_CARGO_CAPACITY,
|
||||
}, {
|
||||
/* Aircraft */
|
||||
STR_SORT_BY_ENGINE_ID,
|
||||
STR_SORT_BY_COST,
|
||||
STR_SORT_BY_MAX_SPEED,
|
||||
STR_SORT_BY_INTRO_DATE,
|
||||
STR_SORT_BY_NAME,
|
||||
STR_SORT_BY_RUNNING_COST,
|
||||
STR_SORT_BY_RELIABILITY,
|
||||
STR_SORT_BY_CARGO_CAPACITY,
|
||||
STR_SORT_BY_RANGE,
|
||||
}};
|
||||
/* Trains */
|
||||
STR_SORT_BY_ENGINE_ID,
|
||||
STR_SORT_BY_COST,
|
||||
STR_SORT_BY_MAX_SPEED,
|
||||
STR_SORT_BY_POWER,
|
||||
STR_SORT_BY_TRACTIVE_EFFORT,
|
||||
STR_SORT_BY_INTRO_DATE,
|
||||
STR_SORT_BY_NAME,
|
||||
STR_SORT_BY_RUNNING_COST,
|
||||
STR_SORT_BY_POWER_VS_RUNNING_COST,
|
||||
STR_SORT_BY_RELIABILITY,
|
||||
STR_SORT_BY_CARGO_CAPACITY,
|
||||
},
|
||||
{
|
||||
/* Road vehicles */
|
||||
STR_SORT_BY_ENGINE_ID,
|
||||
STR_SORT_BY_COST,
|
||||
STR_SORT_BY_MAX_SPEED,
|
||||
STR_SORT_BY_POWER,
|
||||
STR_SORT_BY_TRACTIVE_EFFORT,
|
||||
STR_SORT_BY_INTRO_DATE,
|
||||
STR_SORT_BY_NAME,
|
||||
STR_SORT_BY_RUNNING_COST,
|
||||
STR_SORT_BY_POWER_VS_RUNNING_COST,
|
||||
STR_SORT_BY_RELIABILITY,
|
||||
STR_SORT_BY_CARGO_CAPACITY,
|
||||
},
|
||||
{
|
||||
/* Ships */
|
||||
STR_SORT_BY_ENGINE_ID,
|
||||
STR_SORT_BY_COST,
|
||||
STR_SORT_BY_MAX_SPEED,
|
||||
STR_SORT_BY_INTRO_DATE,
|
||||
STR_SORT_BY_NAME,
|
||||
STR_SORT_BY_RUNNING_COST,
|
||||
STR_SORT_BY_RELIABILITY,
|
||||
STR_SORT_BY_CARGO_CAPACITY,
|
||||
},
|
||||
{
|
||||
/* Aircraft */
|
||||
STR_SORT_BY_ENGINE_ID,
|
||||
STR_SORT_BY_COST,
|
||||
STR_SORT_BY_MAX_SPEED,
|
||||
STR_SORT_BY_INTRO_DATE,
|
||||
STR_SORT_BY_NAME,
|
||||
STR_SORT_BY_RUNNING_COST,
|
||||
STR_SORT_BY_RELIABILITY,
|
||||
STR_SORT_BY_CARGO_CAPACITY,
|
||||
STR_SORT_BY_RANGE,
|
||||
}};
|
||||
|
||||
/** Filters vehicles by cargo and engine (in case of rail vehicle). */
|
||||
static bool CargoAndEngineFilter(const GUIEngineListItem *item, const CargoType cargo_type)
|
||||
|
@ -548,7 +554,7 @@ static bool CargoAndEngineFilter(const GUIEngineListItem *item, const CargoType
|
|||
}
|
||||
}
|
||||
|
||||
static GUIEngineList::FilterFunction * const _engine_filter_funcs[] = {
|
||||
static GUIEngineList::FilterFunction *const _engine_filter_funcs[] = {
|
||||
&CargoAndEngineFilter,
|
||||
};
|
||||
|
||||
|
@ -595,8 +601,7 @@ static int DrawRailWagonPurchaseInfo(int left, int right, int y, EngineID engine
|
|||
|
||||
/* Wagon weight - (including cargo) */
|
||||
uint weight = e->GetDisplayWeight();
|
||||
DrawString(left, right, y,
|
||||
GetString(STR_PURCHASE_INFO_WEIGHT_CWEIGHT, weight, GetCargoWeight(te.all_capacities, VEH_TRAIN) + weight));
|
||||
DrawString(left, right, y, GetString(STR_PURCHASE_INFO_WEIGHT_CWEIGHT, weight, GetCargoWeight(te.all_capacities, VEH_TRAIN) + weight));
|
||||
y += GetCharacterHeight(FS_NORMAL);
|
||||
|
||||
/* Wagon speed limit, displayed if above zero */
|
||||
|
@ -790,7 +795,6 @@ static int DrawAircraftPurchaseInfo(int left, int right, int y, EngineID engine_
|
|||
return y;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Try to get the NewGRF engine additional text callback as an optional std::string.
|
||||
* @param engine The engine whose additional text to get.
|
||||
|
@ -858,7 +862,8 @@ int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number,
|
|||
bool articulated_cargo = false;
|
||||
|
||||
switch (e->type) {
|
||||
default: NOT_REACHED();
|
||||
default:
|
||||
NOT_REACHED();
|
||||
case VEH_TRAIN:
|
||||
if (e->u.rail.railveh_type == RAILVEH_WAGON) {
|
||||
y = DrawRailWagonPurchaseInfo(left, right, y, engine_number, &e->u.rail, te);
|
||||
|
@ -914,8 +919,7 @@ int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number,
|
|||
|
||||
/* The NewGRF's name which the vehicle comes from */
|
||||
const GRFConfig *config = GetGRFConfig(e->GetGRFID());
|
||||
if (_settings_client.gui.show_newgrf_name && config != nullptr)
|
||||
{
|
||||
if (_settings_client.gui.show_newgrf_name && config != nullptr) {
|
||||
DrawString(left, right, y, config->GetName(), TC_BLACK);
|
||||
y += GetCharacterHeight(FS_NORMAL);
|
||||
}
|
||||
|
@ -938,15 +942,16 @@ static void DrawEngineBadgeColumn(const Rect &r, int column_group, const GUIBadg
|
|||
* @param show_count Whether to show the amount of engines or not
|
||||
* @param selected_group the group to list the engines of
|
||||
*/
|
||||
void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_list, const Scrollbar &sb, EngineID selected_id, bool show_count, GroupID selected_group, const GUIBadgeClasses &badge_classes)
|
||||
void DrawEngineList(
|
||||
VehicleType type, const Rect &r, const GUIEngineList &eng_list, const Scrollbar &sb, EngineID selected_id, bool show_count, GroupID selected_group, const GUIBadgeClasses &badge_classes)
|
||||
{
|
||||
static const std::array<int8_t, VehicleType::VEH_COMPANY_END> sprite_y_offsets = { 0, 0, -1, -1 };
|
||||
static const std::array<int8_t, VehicleType::VEH_COMPANY_END> sprite_y_offsets = {0, 0, -1, -1};
|
||||
|
||||
auto [first, last] = sb.GetVisibleRangeIterators(eng_list);
|
||||
|
||||
bool rtl = _current_text_dir == TD_RTL;
|
||||
int step_size = GetEngineListHeight(type);
|
||||
int sprite_left = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_left;
|
||||
int sprite_left = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_left;
|
||||
int sprite_right = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_right;
|
||||
int sprite_width = sprite_left + sprite_right;
|
||||
int circle_width = std::max(GetScaledSpriteSize(SPR_CIRCLE_FOLDED).width, GetScaledSpriteSize(SPR_CIRCLE_UNFOLDED).width);
|
||||
|
@ -973,7 +978,7 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
|
|||
|
||||
const int text_row_height = ir.Shrink(WidgetDimensions::scaled.matrix).Height();
|
||||
const int normal_text_y_offset = (text_row_height - GetCharacterHeight(FS_NORMAL)) / 2;
|
||||
const int small_text_y_offset = text_row_height - GetCharacterHeight(FS_SMALL);
|
||||
const int small_text_y_offset = text_row_height - GetCharacterHeight(FS_SMALL);
|
||||
|
||||
const int offset = (rtl ? -circle_width : circle_width) / 2;
|
||||
const int level_width = rtl ? -WidgetDimensions::scaled.hsep_indent : WidgetDimensions::scaled.hsep_indent;
|
||||
|
@ -982,10 +987,10 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
|
|||
const auto &item = *it;
|
||||
const Engine *e = Engine::Get(item.engine_id);
|
||||
|
||||
uint indent = item.indent * WidgetDimensions::scaled.hsep_indent;
|
||||
uint indent = item.indent * WidgetDimensions::scaled.hsep_indent;
|
||||
bool has_variants = item.flags.Test(EngineDisplayFlag::HasVariants);
|
||||
bool is_folded = item.flags.Test(EngineDisplayFlag::IsFolded);
|
||||
bool shaded = item.flags.Test(EngineDisplayFlag::Shaded);
|
||||
bool is_folded = item.flags.Test(EngineDisplayFlag::IsFolded);
|
||||
bool shaded = item.flags.Test(EngineDisplayFlag::Shaded);
|
||||
|
||||
Rect textr = ir.Shrink(WidgetDimensions::scaled.matrix);
|
||||
Rect tr = ir.Indent(indent, rtl);
|
||||
|
@ -1058,7 +1063,7 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
|
|||
|
||||
/* If the count is visible then this is part of in-use autoreplace list. */
|
||||
auto engine_name = PackEngineNameDParam(item.engine_id, show_count ? EngineNameContext::AutoreplaceVehicleInUse : EngineNameContext::PurchaseList, item.indent);
|
||||
DrawString(tr.left, tr.right, textr.top + normal_text_y_offset,GetString(str, engine_name), tc);
|
||||
DrawString(tr.left, tr.right, textr.top + normal_text_y_offset, GetString(str, engine_name), tc);
|
||||
|
||||
ir = ir.Translate(0, step_size);
|
||||
}
|
||||
|
@ -1133,10 +1138,12 @@ enum BuildVehicleHotkeys : int32_t {
|
|||
/** GUI for building vehicles. */
|
||||
struct BuildVehicleWindow : Window {
|
||||
VehicleType vehicle_type = VEH_INVALID; ///< Type of vehicles shown in the window.
|
||||
|
||||
union {
|
||||
RailType railtype; ///< Rail type to show, or #INVALID_RAILTYPE.
|
||||
RoadType roadtype; ///< Road type to show, or #INVALID_ROADTYPE.
|
||||
RailType railtype; ///< Rail type to show, or #INVALID_RAILTYPE.
|
||||
RoadType roadtype; ///< Road type to show, or #INVALID_ROADTYPE.
|
||||
} filter{}; ///< Filter to apply.
|
||||
|
||||
bool descending_sort_order = false; ///< Sort direction, @see _engine_sort_direction
|
||||
uint8_t sort_criteria = 0; ///< Current sort criterium.
|
||||
bool show_hidden_engines = false; ///< State of the 'show hidden engines' button.
|
||||
|
@ -1157,7 +1164,8 @@ struct BuildVehicleWindow : Window {
|
|||
{
|
||||
NWidgetCore *widget = this->GetWidget<NWidgetCore>(WID_BV_BUILD);
|
||||
|
||||
bool refit = this->sel_engine != EngineID::Invalid() && this->cargo_filter_criteria != CargoFilterCriteria::CF_ANY && this->cargo_filter_criteria != CargoFilterCriteria::CF_NONE && this->cargo_filter_criteria != CargoFilterCriteria::CF_ENGINES;
|
||||
bool refit = this->sel_engine != EngineID::Invalid() && this->cargo_filter_criteria != CargoFilterCriteria::CF_ANY && this->cargo_filter_criteria != CargoFilterCriteria::CF_NONE &&
|
||||
this->cargo_filter_criteria != CargoFilterCriteria::CF_ENGINES;
|
||||
if (refit) refit = Engine::Get(this->sel_engine)->GetDefaultCargoType() != this->cargo_filter_criteria;
|
||||
|
||||
if (refit) {
|
||||
|
@ -1173,9 +1181,9 @@ struct BuildVehicleWindow : Window {
|
|||
this->listview_mode = tile == INVALID_TILE;
|
||||
this->window_number = this->listview_mode ? (int)type : tile.base();
|
||||
|
||||
this->sort_criteria = _engine_sort_last_criteria[type];
|
||||
this->sort_criteria = _engine_sort_last_criteria[type];
|
||||
this->descending_sort_order = _engine_sort_last_order[type];
|
||||
this->show_hidden_engines = _engine_sort_show_hidden_engines[type];
|
||||
this->show_hidden_engines = _engine_sort_show_hidden_engines[type];
|
||||
|
||||
this->UpdateFilterByTile();
|
||||
|
||||
|
@ -1218,7 +1226,9 @@ struct BuildVehicleWindow : Window {
|
|||
|
||||
/* Select the first unshaded engine in the list as default when opening the window */
|
||||
EngineID engine = EngineID::Invalid();
|
||||
auto it = std::ranges::find_if(this->eng_list, [](const GUIEngineListItem &item) { return !item.flags.Test(EngineDisplayFlag::Shaded); });
|
||||
auto it = std::ranges::find_if(this->eng_list, [](const GUIEngineListItem &item) {
|
||||
return !item.flags.Test(EngineDisplayFlag::Shaded);
|
||||
});
|
||||
if (it != this->eng_list.end()) engine = it->engine_id;
|
||||
this->SelectEngine(engine);
|
||||
}
|
||||
|
@ -1227,7 +1237,8 @@ struct BuildVehicleWindow : Window {
|
|||
void UpdateFilterByTile()
|
||||
{
|
||||
switch (this->vehicle_type) {
|
||||
default: NOT_REACHED();
|
||||
default:
|
||||
NOT_REACHED();
|
||||
case VEH_TRAIN:
|
||||
if (this->listview_mode) {
|
||||
this->filter.railtype = INVALID_RAILTYPE;
|
||||
|
@ -1256,10 +1267,14 @@ struct BuildVehicleWindow : Window {
|
|||
StringID GetCargoFilterLabel(CargoType cargo_type) const
|
||||
{
|
||||
switch (cargo_type) {
|
||||
case CargoFilterCriteria::CF_ANY: return STR_PURCHASE_INFO_ALL_TYPES;
|
||||
case CargoFilterCriteria::CF_ENGINES: return STR_PURCHASE_INFO_ENGINES_ONLY;
|
||||
case CargoFilterCriteria::CF_NONE: return STR_PURCHASE_INFO_NONE;
|
||||
default: return CargoSpec::Get(cargo_type)->name;
|
||||
case CargoFilterCriteria::CF_ANY:
|
||||
return STR_PURCHASE_INFO_ALL_TYPES;
|
||||
case CargoFilterCriteria::CF_ENGINES:
|
||||
return STR_PURCHASE_INFO_ENGINES_ONLY;
|
||||
case CargoFilterCriteria::CF_NONE:
|
||||
return STR_PURCHASE_INFO_NONE;
|
||||
default:
|
||||
return CargoSpec::Get(cargo_type)->name;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1288,19 +1303,20 @@ struct BuildVehicleWindow : Window {
|
|||
|
||||
if (!this->listview_mode) {
|
||||
/* Query for cost and refitted capacity */
|
||||
auto [ret, veh_id, refit_capacity, refit_mail, cargo_capacities] = Command<CMD_BUILD_VEHICLE>::Do(DoCommandFlag::QueryCost, TileIndex(this->window_number), this->sel_engine, true, cargo, INVALID_CLIENT_ID);
|
||||
auto [ret, veh_id, refit_capacity, refit_mail, cargo_capacities] =
|
||||
Command<CMD_BUILD_VEHICLE>::Do(DoCommandFlag::QueryCost, TileIndex(this->window_number), this->sel_engine, true, cargo, INVALID_CLIENT_ID);
|
||||
if (ret.Succeeded()) {
|
||||
this->te.cost = ret.GetCost() - e->GetCost();
|
||||
this->te.capacity = refit_capacity;
|
||||
this->te.cost = ret.GetCost() - e->GetCost();
|
||||
this->te.capacity = refit_capacity;
|
||||
this->te.mail_capacity = refit_mail;
|
||||
this->te.cargo = !IsValidCargoType(cargo) ? e->GetDefaultCargoType() : cargo;
|
||||
this->te.cargo = !IsValidCargoType(cargo) ? e->GetDefaultCargoType() : cargo;
|
||||
this->te.all_capacities = cargo_capacities;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Purchase test was not possible or failed, fill in the defaults instead. */
|
||||
this->te.cost = 0;
|
||||
this->te.cost = 0;
|
||||
this->te.FillDefaultCapacities(e);
|
||||
}
|
||||
|
||||
|
@ -1316,7 +1332,8 @@ struct BuildVehicleWindow : Window {
|
|||
this->eng_list.Filter(this->cargo_filter_criteria);
|
||||
if (0 == this->eng_list.size()) { // no engine passed through the filter, invalidate the previously selected engine
|
||||
this->SelectEngine(EngineID::Invalid());
|
||||
} else if (std::ranges::find(this->eng_list, this->sel_engine, &GUIEngineListItem::engine_id) == this->eng_list.end()) { // previously selected engine didn't pass the filter, select the first engine of the list
|
||||
} else if (std::ranges::find(this->eng_list, this->sel_engine, &GUIEngineListItem::engine_id) ==
|
||||
this->eng_list.end()) { // previously selected engine didn't pass the filter, select the first engine of the list
|
||||
this->SelectEngine(this->eng_list[0].engine_id);
|
||||
}
|
||||
}
|
||||
|
@ -1508,7 +1525,8 @@ struct BuildVehicleWindow : Window {
|
|||
GUIEngineList list;
|
||||
|
||||
switch (this->vehicle_type) {
|
||||
default: NOT_REACHED();
|
||||
default:
|
||||
NOT_REACHED();
|
||||
case VEH_TRAIN:
|
||||
this->GenerateBuildTrainList(list);
|
||||
GUIEngineListAddChildren(this->eng_list, list);
|
||||
|
@ -1628,7 +1646,10 @@ struct BuildVehicleWindow : Window {
|
|||
const auto it = this->vscroll->GetScrolledItemFromWidget(this->eng_list, pt.y, this, WID_BV_LIST);
|
||||
if (it != this->eng_list.end()) {
|
||||
const auto &item = *it;
|
||||
const Rect r = this->GetWidget<NWidgetBase>(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.matrix).WithWidth(WidgetDimensions::scaled.hsep_indent * (item.indent + 1), _current_text_dir == TD_RTL);
|
||||
const Rect r = this->GetWidget<NWidgetBase>(widget)
|
||||
->GetCurrentRect()
|
||||
.Shrink(WidgetDimensions::scaled.matrix)
|
||||
.WithWidth(WidgetDimensions::scaled.hsep_indent * (item.indent + 1), _current_text_dir == TD_RTL);
|
||||
if (item.flags.Test(EngineDisplayFlag::HasVariants) && IsInsideMM(r.left, r.right, pt.x)) {
|
||||
/* toggle folded flag on engine */
|
||||
assert(item.variant_id != EngineID::Invalid());
|
||||
|
@ -1675,7 +1696,8 @@ struct BuildVehicleWindow : Window {
|
|||
EngineID sel_eng = this->sel_engine;
|
||||
if (sel_eng != EngineID::Invalid()) {
|
||||
this->rename_engine = sel_eng;
|
||||
ShowQueryString(GetString(STR_ENGINE_NAME, PackEngineNameDParam(sel_eng, EngineNameContext::Generic)), STR_QUERY_RENAME_TRAIN_TYPE_CAPTION + this->vehicle_type, MAX_LENGTH_ENGINE_NAME_CHARS, this, CS_ALPHANUMERAL, {QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars});
|
||||
ShowQueryString(GetString(STR_ENGINE_NAME, PackEngineNameDParam(sel_eng, EngineNameContext::Generic)), STR_QUERY_RENAME_TRAIN_TYPE_CAPTION + this->vehicle_type,
|
||||
MAX_LENGTH_ENGINE_NAME_CHARS, this, CS_ALPHANUMERAL, {QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1691,9 +1713,7 @@ struct BuildVehicleWindow : Window {
|
|||
{
|
||||
if (!gui_scope) return;
|
||||
/* When switching to original acceleration model for road vehicles, clear the selected sort criteria if it is not available now. */
|
||||
if (this->vehicle_type == VEH_ROAD &&
|
||||
_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL &&
|
||||
this->sort_criteria > 7) {
|
||||
if (this->vehicle_type == VEH_ROAD && _settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL && this->sort_criteria > 7) {
|
||||
this->sort_criteria = 0;
|
||||
_engine_sort_last_criteria[VEH_ROAD] = 0;
|
||||
}
|
||||
|
@ -1739,7 +1759,10 @@ struct BuildVehicleWindow : Window {
|
|||
case WID_BV_LIST:
|
||||
resize.height = GetEngineListHeight(this->vehicle_type);
|
||||
size.height = 3 * resize.height;
|
||||
size.width = std::max(size.width, this->badge_classes.GetTotalColumnsWidth() + GetVehicleImageCellSize(this->vehicle_type, EIT_PURCHASE).extend_left + GetVehicleImageCellSize(this->vehicle_type, EIT_PURCHASE).extend_right + 165) + padding.width;
|
||||
size.width = std::max(size.width,
|
||||
this->badge_classes.GetTotalColumnsWidth() + GetVehicleImageCellSize(this->vehicle_type, EIT_PURCHASE).extend_left +
|
||||
GetVehicleImageCellSize(this->vehicle_type, EIT_PURCHASE).extend_right + 165) +
|
||||
padding.width;
|
||||
break;
|
||||
|
||||
case WID_BV_PANEL:
|
||||
|
@ -1778,16 +1801,7 @@ struct BuildVehicleWindow : Window {
|
|||
{
|
||||
switch (widget) {
|
||||
case WID_BV_LIST:
|
||||
DrawEngineList(
|
||||
this->vehicle_type,
|
||||
r,
|
||||
this->eng_list,
|
||||
*this->vscroll,
|
||||
this->sel_engine,
|
||||
false,
|
||||
DEFAULT_GROUP,
|
||||
this->badge_classes
|
||||
);
|
||||
DrawEngineList(this->vehicle_type, r, this->eng_list, *this->vscroll, this->sel_engine, false, DEFAULT_GROUP, this->badge_classes);
|
||||
break;
|
||||
|
||||
case WID_BV_SORT_ASCENDING_DESCENDING:
|
||||
|
@ -1885,18 +1899,13 @@ struct BuildVehicleWindow : Window {
|
|||
return ES_HANDLED;
|
||||
}
|
||||
|
||||
static inline HotkeyList hotkeys{"buildvehicle", {
|
||||
Hotkey('F', "focus_filter_box", BVHK_FOCUS_FILTER_BOX),
|
||||
}};
|
||||
static inline HotkeyList hotkeys{"buildvehicle",
|
||||
{
|
||||
Hotkey('F', "focus_filter_box", BVHK_FOCUS_FILTER_BOX),
|
||||
}};
|
||||
};
|
||||
|
||||
static WindowDesc _build_vehicle_desc(
|
||||
WDP_AUTO, "build_vehicle", 240, 268,
|
||||
WC_BUILD_VEHICLE, WC_NONE,
|
||||
WindowDefaultFlag::Construction,
|
||||
_nested_build_vehicle_widgets,
|
||||
&BuildVehicleWindow::hotkeys
|
||||
);
|
||||
static WindowDesc _build_vehicle_desc(WDP_AUTO, "build_vehicle", 240, 268, WC_BUILD_VEHICLE, WC_NONE, WindowDefaultFlag::Construction, _nested_build_vehicle_widgets, &BuildVehicleWindow::hotkeys);
|
||||
|
||||
void ShowBuildVehicleWindow(TileIndex tile, VehicleType type)
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
/** @file cachecheck.cpp Check caches. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "aircraft.h"
|
||||
#include "company_base.h"
|
||||
#include "debug.h"
|
||||
|
@ -105,11 +106,20 @@ void CheckCaches()
|
|||
}
|
||||
|
||||
switch (v->type) {
|
||||
case VEH_TRAIN: Train::From(v)->ConsistChanged(CCF_TRACK); break;
|
||||
case VEH_ROAD: RoadVehUpdateCache(RoadVehicle::From(v)); break;
|
||||
case VEH_AIRCRAFT: UpdateAircraftCache(Aircraft::From(v)); break;
|
||||
case VEH_SHIP: Ship::From(v)->UpdateCache(); break;
|
||||
default: break;
|
||||
case VEH_TRAIN:
|
||||
Train::From(v)->ConsistChanged(CCF_TRACK);
|
||||
break;
|
||||
case VEH_ROAD:
|
||||
RoadVehUpdateCache(RoadVehicle::From(v));
|
||||
break;
|
||||
case VEH_AIRCRAFT:
|
||||
UpdateAircraftCache(Aircraft::From(v));
|
||||
break;
|
||||
case VEH_SHIP:
|
||||
Ship::From(v)->UpdateCache();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
uint length = 0;
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
#ifndef CARGO_TYPE_H
|
||||
#define CARGO_TYPE_H
|
||||
|
||||
#include "core/convertible_through_base.hpp"
|
||||
#include "core/enum_type.hpp"
|
||||
#include "core/strong_typedef_type.hpp"
|
||||
#include "core/convertible_through_base.hpp"
|
||||
|
||||
/** Globally unique label of a cargo type. */
|
||||
using CargoLabel = StrongType::Typedef<uint32_t, struct CargoLabelTag, StrongType::Compare>;
|
||||
|
@ -92,18 +92,21 @@ enum MixedCargoType : uint8_t {
|
|||
* These are used by user interface code only and must not be assigned to any entity. Not all values are valid for every UI filter.
|
||||
*/
|
||||
namespace CargoFilterCriteria {
|
||||
static constexpr CargoType CF_ANY = NUM_CARGO; ///< Show all items independent of carried cargo (i.e. no filtering)
|
||||
static constexpr CargoType CF_NONE = NUM_CARGO + 1; ///< Show only items which do not carry cargo (e.g. train engines)
|
||||
static constexpr CargoType CF_ANY = NUM_CARGO; ///< Show all items independent of carried cargo (i.e. no filtering)
|
||||
static constexpr CargoType CF_NONE = NUM_CARGO + 1; ///< Show only items which do not carry cargo (e.g. train engines)
|
||||
static constexpr CargoType CF_ENGINES = NUM_CARGO + 2; ///< Show only engines (for rail vehicles only)
|
||||
static constexpr CargoType CF_FREIGHT = NUM_CARGO + 3; ///< Show only vehicles which carry any freight (non-passenger) cargo
|
||||
|
||||
static constexpr CargoType CF_NO_RATING = NUM_CARGO + 4; ///< Show items with no rating (station list)
|
||||
static constexpr CargoType CF_SELECT_ALL = NUM_CARGO + 5; ///< Select all items (station list)
|
||||
static constexpr CargoType CF_NO_RATING = NUM_CARGO + 4; ///< Show items with no rating (station list)
|
||||
static constexpr CargoType CF_SELECT_ALL = NUM_CARGO + 5; ///< Select all items (station list)
|
||||
static constexpr CargoType CF_EXPAND_LIST = NUM_CARGO + 6; ///< Expand list to show all items (station list)
|
||||
};
|
||||
|
||||
/** Test whether cargo type is not INVALID_CARGO */
|
||||
inline bool IsValidCargoType(CargoType cargo) { return cargo != INVALID_CARGO; }
|
||||
inline bool IsValidCargoType(CargoType cargo)
|
||||
{
|
||||
return cargo != INVALID_CARGO;
|
||||
}
|
||||
|
||||
typedef uint64_t CargoTypes;
|
||||
|
||||
|
@ -127,7 +130,9 @@ struct CargoArray : std::array<uint, NUM_CARGO> {
|
|||
*/
|
||||
inline uint GetCount() const
|
||||
{
|
||||
return std::ranges::count_if(*this, [](uint amount) { return amount != 0; });
|
||||
return std::ranges::count_if(*this, [](uint amount) {
|
||||
return amount != 0;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
/** @file cargoaction.cpp Implementation of cargo actions. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "economy_base.h"
|
||||
|
||||
#include "cargoaction.h"
|
||||
|
||||
#include "economy_base.h"
|
||||
#include "station_base.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
|
|
@ -20,9 +20,10 @@ template <class Tsource>
|
|||
class CargoRemoval {
|
||||
protected:
|
||||
Tsource *source; ///< Source of the cargo.
|
||||
uint max_move; ///< Maximum amount of cargo to be removed with this action.
|
||||
uint max_move; ///< Maximum amount of cargo to be removed with this action.
|
||||
uint Preprocess(CargoPacket *cp);
|
||||
bool Postprocess(CargoPacket *cp, uint remove);
|
||||
|
||||
public:
|
||||
CargoRemoval(Tsource *source, uint max_move) : source(source), max_move(max_move) {}
|
||||
|
||||
|
@ -30,7 +31,10 @@ public:
|
|||
* Returns how much more cargo can be removed with this action.
|
||||
* @return Amount of cargo this action can still remove.
|
||||
*/
|
||||
uint MaxMove() { return this->max_move; }
|
||||
uint MaxMove()
|
||||
{
|
||||
return this->max_move;
|
||||
}
|
||||
|
||||
bool operator()(CargoPacket *cp);
|
||||
};
|
||||
|
@ -43,7 +47,10 @@ protected:
|
|||
CargoType cargo; ///< The cargo type of the cargo.
|
||||
public:
|
||||
CargoDelivery(VehicleCargoList *source, uint max_move, CargoType cargo, CargoPayment *payment, TileIndex current_tile) :
|
||||
CargoRemoval<VehicleCargoList>(source, max_move), current_tile(current_tile), payment(payment), cargo(cargo) {}
|
||||
CargoRemoval<VehicleCargoList>(source, max_move), current_tile(current_tile), payment(payment), cargo(cargo)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(CargoPacket *cp);
|
||||
};
|
||||
|
||||
|
@ -55,10 +62,11 @@ public:
|
|||
template <class Tsource, class Tdest>
|
||||
class CargoMovement {
|
||||
protected:
|
||||
Tsource *source; ///< Source of the cargo.
|
||||
Tsource *source; ///< Source of the cargo.
|
||||
Tdest *destination; ///< Destination for the cargo.
|
||||
uint max_move; ///< Maximum amount of cargo to be moved with this action.
|
||||
uint max_move; ///< Maximum amount of cargo to be moved with this action.
|
||||
CargoPacket *Preprocess(CargoPacket *cp);
|
||||
|
||||
public:
|
||||
CargoMovement(Tsource *source, Tdest *destination, uint max_move) : source(source), destination(destination), max_move(max_move) {}
|
||||
|
||||
|
@ -66,7 +74,10 @@ public:
|
|||
* Returns how much more cargo can be moved with this action.
|
||||
* @return Amount of cargo this action can still move.
|
||||
*/
|
||||
uint MaxMove() { return this->max_move; }
|
||||
uint MaxMove()
|
||||
{
|
||||
return this->max_move;
|
||||
}
|
||||
};
|
||||
|
||||
/** Action of transferring cargo from a vehicle to a station. */
|
||||
|
@ -75,7 +86,10 @@ protected:
|
|||
TileIndex current_tile; ///< Current tile cargo unloading is happening.
|
||||
public:
|
||||
CargoTransfer(VehicleCargoList *source, StationCargoList *destination, uint max_move, TileIndex current_tile) :
|
||||
CargoMovement<VehicleCargoList, StationCargoList>(source, destination, max_move), current_tile(current_tile) {}
|
||||
CargoMovement<VehicleCargoList, StationCargoList>(source, destination, max_move), current_tile(current_tile)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(CargoPacket *cp);
|
||||
};
|
||||
|
||||
|
@ -85,15 +99,18 @@ protected:
|
|||
TileIndex current_tile; ///< Current tile cargo loading is happening.
|
||||
public:
|
||||
CargoLoad(StationCargoList *source, VehicleCargoList *destination, uint max_move, TileIndex current_tile) :
|
||||
CargoMovement<StationCargoList, VehicleCargoList>(source, destination, max_move), current_tile(current_tile) {}
|
||||
CargoMovement<StationCargoList, VehicleCargoList>(source, destination, max_move), current_tile(current_tile)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(CargoPacket *cp);
|
||||
};
|
||||
|
||||
/** Action of reserving cargo from a station to be loaded onto a vehicle. */
|
||||
class CargoReservation : public CargoLoad {
|
||||
public:
|
||||
CargoReservation(StationCargoList *source, VehicleCargoList *destination, uint max_move, TileIndex current_tile) :
|
||||
CargoLoad(source, destination, max_move, current_tile) {}
|
||||
CargoReservation(StationCargoList *source, VehicleCargoList *destination, uint max_move, TileIndex current_tile) : CargoLoad(source, destination, max_move, current_tile) {}
|
||||
|
||||
bool operator()(CargoPacket *cp);
|
||||
};
|
||||
|
||||
|
@ -102,17 +119,21 @@ class CargoReturn : public CargoMovement<VehicleCargoList, StationCargoList> {
|
|||
protected:
|
||||
TileIndex current_tile; ///< Current tile cargo unloading is happening.
|
||||
StationID next;
|
||||
|
||||
public:
|
||||
CargoReturn(VehicleCargoList *source, StationCargoList *destination, uint max_move, StationID next, TileIndex current_tile) :
|
||||
CargoMovement<VehicleCargoList, StationCargoList>(source, destination, max_move), current_tile(current_tile), next(next) {}
|
||||
CargoMovement<VehicleCargoList, StationCargoList>(source, destination, max_move), current_tile(current_tile), next(next)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(CargoPacket *cp);
|
||||
};
|
||||
|
||||
/** Action of shifting cargo from one vehicle to another. */
|
||||
class CargoShift : public CargoMovement<VehicleCargoList, VehicleCargoList> {
|
||||
public:
|
||||
CargoShift(VehicleCargoList *source, VehicleCargoList *destination, uint max_move) :
|
||||
CargoMovement<VehicleCargoList, VehicleCargoList>(source, destination, max_move) {}
|
||||
CargoShift(VehicleCargoList *source, VehicleCargoList *destination, uint max_move) : CargoMovement<VehicleCargoList, VehicleCargoList>(source, destination, max_move) {}
|
||||
|
||||
bool operator()(CargoPacket *cp);
|
||||
};
|
||||
|
||||
|
@ -123,16 +144,22 @@ protected:
|
|||
StationID avoid;
|
||||
StationID avoid2;
|
||||
const GoodsEntry *ge;
|
||||
|
||||
public:
|
||||
CargoReroute(Tlist *source, Tlist *dest, uint max_move, StationID avoid, StationID avoid2, const GoodsEntry *ge) :
|
||||
CargoMovement<Tlist, Tlist>(source, dest, max_move), avoid(avoid), avoid2(avoid2), ge(ge) {}
|
||||
CargoMovement<Tlist, Tlist>(source, dest, max_move), avoid(avoid), avoid2(avoid2), ge(ge)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/** Action of rerouting cargo in a station. */
|
||||
class StationCargoReroute : public CargoReroute<StationCargoList> {
|
||||
public:
|
||||
StationCargoReroute(StationCargoList *source, StationCargoList *dest, uint max_move, StationID avoid, StationID avoid2, const GoodsEntry *ge) :
|
||||
CargoReroute<StationCargoList>(source, dest, max_move, avoid, avoid2, ge) {}
|
||||
CargoReroute<StationCargoList>(source, dest, max_move, avoid, avoid2, ge)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(CargoPacket *cp);
|
||||
};
|
||||
|
||||
|
@ -140,10 +167,11 @@ public:
|
|||
class VehicleCargoReroute : public CargoReroute<VehicleCargoList> {
|
||||
public:
|
||||
VehicleCargoReroute(VehicleCargoList *source, VehicleCargoList *dest, uint max_move, StationID avoid, StationID avoid2, const GoodsEntry *ge) :
|
||||
CargoReroute<VehicleCargoList>(source, dest, max_move, avoid, avoid2, ge)
|
||||
CargoReroute<VehicleCargoList>(source, dest, max_move, avoid, avoid2, ge)
|
||||
{
|
||||
assert(this->max_move <= source->ActionCount(VehicleCargoList::MTA_TRANSFER));
|
||||
}
|
||||
|
||||
bool operator()(CargoPacket *cp);
|
||||
};
|
||||
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
/** @file cargomonitor.cpp Implementation of the cargo transport monitoring. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "cargomonitor.h"
|
||||
|
||||
#include "station_base.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
CargoMonitorMap _cargo_pickups; ///< Map of monitored pick-ups to the amount since last query/activation.
|
||||
CargoMonitorMap _cargo_pickups; ///< Map of monitored pick-ups to the amount since last query/activation.
|
||||
CargoMonitorMap _cargo_deliveries; ///< Map of monitored deliveries to the amount since last query/activation.
|
||||
|
||||
/**
|
||||
|
@ -133,7 +135,8 @@ void AddCargoDelivery(CargoType cargo_type, CompanyID company, uint32_t amount,
|
|||
if (iter != _cargo_pickups.end()) iter->second += amount;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,4 +156,3 @@ void AddCargoDelivery(CargoType cargo_type, CompanyID company, uint32_t amount,
|
|||
if (iter != _cargo_deliveries.end()) iter->second += amount;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
#ifndef CARGOMONITOR_H
|
||||
#define CARGOMONITOR_H
|
||||
|
||||
#include "core/overflowsafe_type.hpp"
|
||||
#include "cargo_type.h"
|
||||
#include "company_func.h"
|
||||
#include "industry.h"
|
||||
#include "town.h"
|
||||
#include "core/overflowsafe_type.hpp"
|
||||
|
||||
struct Station;
|
||||
|
||||
|
@ -34,7 +34,6 @@ typedef std::map<CargoMonitorID, OverflowSafeInt32> CargoMonitorMap;
|
|||
extern CargoMonitorMap _cargo_pickups;
|
||||
extern CargoMonitorMap _cargo_deliveries;
|
||||
|
||||
|
||||
/* Constants for encoding and extracting cargo monitors. */
|
||||
constexpr uint8_t CCB_TOWN_IND_NUMBER_START = 0; ///< Start bit of the town or industry number.
|
||||
constexpr uint8_t CCB_TOWN_IND_NUMBER_LENGTH = 16; ///< Number of bits of the town or industry number.
|
||||
|
@ -44,10 +43,9 @@ constexpr uint8_t CCB_CARGO_TYPE_LENGTH = 6; ///< Number of bits of the cargo ty
|
|||
constexpr uint8_t CCB_COMPANY_START = 25; ///< Start bit of the company field.
|
||||
constexpr uint8_t CCB_COMPANY_LENGTH = 4; ///< Number of bits of the company field.
|
||||
|
||||
static_assert(NUM_CARGO <= (1 << CCB_CARGO_TYPE_LENGTH));
|
||||
static_assert(NUM_CARGO <= (1 << CCB_CARGO_TYPE_LENGTH));
|
||||
static_assert(MAX_COMPANIES <= (1 << CCB_COMPANY_LENGTH));
|
||||
|
||||
|
||||
/**
|
||||
* Encode a cargo monitor for pickup or delivery at an industry.
|
||||
* @param company Company performing the transport.
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
/** @file cargopacket.cpp Implementation of the cargo packets. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "station_base.h"
|
||||
|
||||
#include "core/pool_func.hpp"
|
||||
#include "core/random_func.hpp"
|
||||
#include "economy_base.h"
|
||||
#include "cargoaction.h"
|
||||
#include "economy_base.h"
|
||||
#include "order_type.h"
|
||||
#include "station_base.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
@ -24,9 +25,7 @@ INSTANTIATE_POOL_METHODS(CargoPacket)
|
|||
/**
|
||||
* Create a new packet for savegame loading.
|
||||
*/
|
||||
CargoPacket::CargoPacket()
|
||||
{
|
||||
}
|
||||
CargoPacket::CargoPacket() {}
|
||||
|
||||
/**
|
||||
* Creates a new cargo packet.
|
||||
|
@ -36,10 +35,7 @@ CargoPacket::CargoPacket()
|
|||
* @param source Source of the packet (for subsidies).
|
||||
* @pre count != 0
|
||||
*/
|
||||
CargoPacket::CargoPacket(StationID first_station,uint16_t count, Source source) :
|
||||
count(count),
|
||||
source(source),
|
||||
first_station(first_station)
|
||||
CargoPacket::CargoPacket(StationID first_station, uint16_t count, Source source) : count(count), source(source), first_station(first_station)
|
||||
{
|
||||
assert(count != 0);
|
||||
}
|
||||
|
@ -54,11 +50,7 @@ CargoPacket::CargoPacket(StationID first_station,uint16_t count, Source source)
|
|||
* @param feeder_share Feeder share the packet has already accumulated.
|
||||
*/
|
||||
CargoPacket::CargoPacket(uint16_t count, uint16_t periods_in_transit, StationID first_station, TileIndex source_xy, Money feeder_share) :
|
||||
count(count),
|
||||
periods_in_transit(periods_in_transit),
|
||||
feeder_share(feeder_share),
|
||||
source_xy(source_xy),
|
||||
first_station(first_station)
|
||||
count(count), periods_in_transit(periods_in_transit), feeder_share(feeder_share), source_xy(source_xy), first_station(first_station)
|
||||
{
|
||||
assert(count != 0);
|
||||
}
|
||||
|
@ -71,17 +63,11 @@ CargoPacket::CargoPacket(uint16_t count, uint16_t periods_in_transit, StationID
|
|||
* @param original The original packet we are splitting.
|
||||
*/
|
||||
CargoPacket::CargoPacket(uint16_t count, Money feeder_share, CargoPacket &original) :
|
||||
count(count),
|
||||
periods_in_transit(original.periods_in_transit),
|
||||
feeder_share(feeder_share),
|
||||
source_xy(original.source_xy),
|
||||
travelled(original.travelled),
|
||||
source(original.source),
|
||||
count(count), periods_in_transit(original.periods_in_transit), feeder_share(feeder_share), source_xy(original.source_xy), travelled(original.travelled), source(original.source),
|
||||
#ifdef WITH_ASSERT
|
||||
in_vehicle(original.in_vehicle),
|
||||
in_vehicle(original.in_vehicle),
|
||||
#endif /* WITH_ASSERT */
|
||||
first_station(original.first_station),
|
||||
next_hop(original.next_hop)
|
||||
first_station(original.first_station), next_hop(original.next_hop)
|
||||
{
|
||||
assert(count != 0);
|
||||
}
|
||||
|
@ -222,8 +208,7 @@ void CargoList<Tinst, Tcont>::InvalidateCache()
|
|||
template <class Tinst, class Tcont>
|
||||
/* static */ bool CargoList<Tinst, Tcont>::TryMerge(CargoPacket *icp, CargoPacket *cp)
|
||||
{
|
||||
if (Tinst::AreMergable(icp, cp) &&
|
||||
icp->count + cp->count <= CargoPacket::MAX_COUNT) {
|
||||
if (Tinst::AreMergable(icp, cp) && icp->count + cp->count <= CargoPacket::MAX_COUNT) {
|
||||
icp->Merge(cp);
|
||||
return true;
|
||||
} else {
|
||||
|
@ -255,8 +240,7 @@ template <class Tinst, class Tcont>
|
|||
void VehicleCargoList::Append(CargoPacket *cp, MoveToAction action)
|
||||
{
|
||||
assert(cp != nullptr);
|
||||
assert(action == MTA_LOAD ||
|
||||
(action == MTA_KEEP && this->action_counts[MTA_LOAD] == 0));
|
||||
assert(action == MTA_LOAD || (action == MTA_KEEP && this->action_counts[MTA_LOAD] == 0));
|
||||
this->AddToMeta(cp, action);
|
||||
|
||||
if (this->count == cp->count) {
|
||||
|
@ -403,8 +387,7 @@ void VehicleCargoList::AgeCargo()
|
|||
* @param next_station Next station(s) the vehicle may stop at.
|
||||
* @return MoveToAction to be performed.
|
||||
*/
|
||||
/* static */ VehicleCargoList::MoveToAction VehicleCargoList::ChooseAction(const CargoPacket *cp, StationID cargo_next,
|
||||
StationID current_station, bool accepted, StationIDStack next_station)
|
||||
/* static */ VehicleCargoList::MoveToAction VehicleCargoList::ChooseAction(const CargoPacket *cp, StationID cargo_next, StationID current_station, bool accepted, StationIDStack next_station)
|
||||
{
|
||||
if (cargo_next == StationID::Invalid()) {
|
||||
return (accepted && cp->first_station != current_station) ? MTA_DELIVER : MTA_KEEP;
|
||||
|
@ -432,7 +415,8 @@ void VehicleCargoList::AgeCargo()
|
|||
* @param current_tile Current tile the cargo handling is happening on.
|
||||
* return If any cargo will be unloaded.
|
||||
*/
|
||||
bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
|
||||
bool VehicleCargoList::Stage(
|
||||
bool accepted, StationID current_station, StationIDStack next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
|
||||
{
|
||||
this->AssertCountConsistency();
|
||||
assert(this->action_counts[MTA_LOAD] == 0);
|
||||
|
@ -687,8 +671,7 @@ void StationCargoList::Append(CargoPacket *cp, StationID next)
|
|||
this->AddToCache(cp);
|
||||
|
||||
StationCargoPacketMap::List &list = this->packets[next];
|
||||
for (StationCargoPacketMap::List::reverse_iterator it(list.rbegin());
|
||||
it != list.rend(); it++) {
|
||||
for (StationCargoPacketMap::List::reverse_iterator it(list.rbegin()); it != list.rend(); it++) {
|
||||
if (StationCargoList::TryMerge(*it, cp)) return;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,15 +10,15 @@
|
|||
#ifndef CARGOPACKET_H
|
||||
#define CARGOPACKET_H
|
||||
|
||||
#include "core/pool_type.hpp"
|
||||
#include "economy_type.h"
|
||||
#include "station_type.h"
|
||||
#include "order_type.h"
|
||||
#include "cargo_type.h"
|
||||
#include "source_type.h"
|
||||
#include "vehicle_type.h"
|
||||
#include "core/multimap.hpp"
|
||||
#include "core/pool_type.hpp"
|
||||
#include "cargo_type.h"
|
||||
#include "economy_type.h"
|
||||
#include "order_type.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "source_type.h"
|
||||
#include "station_type.h"
|
||||
#include "vehicle_type.h"
|
||||
|
||||
/** Unique identifier for a single cargo packet. */
|
||||
using CargoPacketID = PoolID<uint32_t, struct CargoPacketIDTag, 0xFFF000, 0xFFFFFF>;
|
||||
|
@ -31,7 +31,8 @@ extern CargoPacketPool _cargopacket_pool;
|
|||
|
||||
struct GoodsEntry; // forward-declare for Stage() and RerouteStalePackets()
|
||||
|
||||
template <class Tinst, class Tcont> class CargoList;
|
||||
template <class Tinst, class Tcont>
|
||||
class CargoList;
|
||||
class StationCargoList; // forward-declare, so we can use it in VehicleCargoList.
|
||||
extern SaveLoadTable GetCargoPacketDesc();
|
||||
|
||||
|
@ -64,11 +65,13 @@ private:
|
|||
StationID next_hop = StationID::Invalid(); ///< Station where the cargo wants to go next.
|
||||
|
||||
/** The CargoList caches, thus needs to know about it. */
|
||||
template <class Tinst, class Tcont> friend class CargoList;
|
||||
template <class Tinst, class Tcont>
|
||||
friend class CargoList;
|
||||
friend class VehicleCargoList;
|
||||
friend class StationCargoList;
|
||||
/** We want this to be saved, right? */
|
||||
friend SaveLoadTable GetCargoPacketDesc();
|
||||
|
||||
public:
|
||||
/** Maximum number of items in a single cargo packet. */
|
||||
static const uint16_t MAX_COUNT = UINT16_MAX;
|
||||
|
@ -79,7 +82,7 @@ public:
|
|||
CargoPacket(uint16_t count, Money feeder_share, CargoPacket &original);
|
||||
|
||||
/** Destroy the packet. */
|
||||
~CargoPacket() { }
|
||||
~CargoPacket() {}
|
||||
|
||||
CargoPacket *Split(uint new_size);
|
||||
void Merge(CargoPacket *cp);
|
||||
|
@ -286,9 +289,9 @@ public:
|
|||
enum MoveToAction : uint8_t {
|
||||
MTA_BEGIN = 0,
|
||||
MTA_TRANSFER = 0, ///< Transfer the cargo to the station.
|
||||
MTA_DELIVER, ///< Deliver the cargo to some town or industry.
|
||||
MTA_KEEP, ///< Keep the cargo in the vehicle.
|
||||
MTA_LOAD, ///< Load the cargo from the station.
|
||||
MTA_DELIVER, ///< Deliver the cargo to some town or industry.
|
||||
MTA_KEEP, ///< Keep the cargo in the vehicle.
|
||||
MTA_LOAD, ///< Load the cargo from the station.
|
||||
MTA_END,
|
||||
NUM_MOVE_TO_ACTION = MTA_END
|
||||
};
|
||||
|
@ -344,7 +347,7 @@ protected:
|
|||
/** The (direct) parent of this class. */
|
||||
typedef CargoList<VehicleCargoList, CargoPacketList> Parent;
|
||||
|
||||
Money feeder_share; ///< Cache for the feeder share.
|
||||
Money feeder_share; ///< Cache for the feeder share.
|
||||
uint action_counts[NUM_MOVE_TO_ACTION]; ///< Counts of cargo to be transferred, delivered, kept and loaded.
|
||||
|
||||
template <class Taction>
|
||||
|
@ -358,10 +361,7 @@ protected:
|
|||
*/
|
||||
inline void AssertCountConsistency() const
|
||||
{
|
||||
assert(this->action_counts[MTA_KEEP] +
|
||||
this->action_counts[MTA_DELIVER] +
|
||||
this->action_counts[MTA_TRANSFER] +
|
||||
this->action_counts[MTA_LOAD] == this->count);
|
||||
assert(this->action_counts[MTA_KEEP] + this->action_counts[MTA_DELIVER] + this->action_counts[MTA_TRANSFER] + this->action_counts[MTA_LOAD] == this->count);
|
||||
}
|
||||
|
||||
void AddToCache(const CargoPacket *cp);
|
||||
|
@ -370,8 +370,7 @@ protected:
|
|||
void AddToMeta(const CargoPacket *cp, MoveToAction action);
|
||||
void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
|
||||
|
||||
static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next,
|
||||
StationID current_station, bool accepted, StationIDStack next_station);
|
||||
static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next, StationID current_station, bool accepted, StationIDStack next_station);
|
||||
|
||||
public:
|
||||
/** The station cargo list needs to control the unloading. */
|
||||
|
@ -503,10 +502,7 @@ public:
|
|||
*/
|
||||
static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
|
||||
{
|
||||
return cp1->source_xy == cp2->source_xy &&
|
||||
cp1->periods_in_transit == cp2->periods_in_transit &&
|
||||
cp1->first_station == cp2->first_station &&
|
||||
cp1->source == cp2->source;
|
||||
return cp1->source_xy == cp2->source_xy && cp1->periods_in_transit == cp2->periods_in_transit && cp1->first_station == cp2->first_station && cp1->source == cp2->source;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -617,10 +613,7 @@ public:
|
|||
*/
|
||||
static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
|
||||
{
|
||||
return cp1->source_xy == cp2->source_xy &&
|
||||
cp1->periods_in_transit == cp2->periods_in_transit &&
|
||||
cp1->first_station == cp2->first_station &&
|
||||
cp1->source == cp2->source;
|
||||
return cp1->source_xy == cp2->source_xy && cp1->periods_in_transit == cp2->periods_in_transit && cp1->first_station == cp2->first_station && cp1->source == cp2->source;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -8,16 +8,18 @@
|
|||
/** @file cargotype.cpp Implementation of cargoes. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "cargotype.h"
|
||||
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "newgrf_cargo.h"
|
||||
#include "settings_type.h"
|
||||
#include "string_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "settings_type.h"
|
||||
|
||||
#include "table/cargo_const.h"
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
#include "table/cargo_const.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
@ -71,13 +73,13 @@ void SetupCargoForClimate(LandscapeType l)
|
|||
/* Copy from default cargo by label or index. */
|
||||
auto insert = std::begin(CargoSpec::array);
|
||||
for (const auto &cl : _default_climate_cargo[to_underlying(l)]) {
|
||||
|
||||
struct visitor {
|
||||
const CargoSpec &operator()(const int &index)
|
||||
{
|
||||
/* Copy the default cargo by index. */
|
||||
return _default_cargo[index];
|
||||
}
|
||||
|
||||
const CargoSpec &operator()(const CargoLabel &label)
|
||||
{
|
||||
/* Search for label in default cargo types and copy if found. */
|
||||
|
@ -153,7 +155,9 @@ bool IsDefaultCargo(CargoType cargo_type)
|
|||
if (!cs->IsValid()) return false;
|
||||
|
||||
CargoLabel label = cs->label;
|
||||
return std::any_of(std::begin(_default_cargo_labels), std::end(_default_cargo_labels), [&label](const CargoLabel &cl) { return cl == label; });
|
||||
return std::any_of(std::begin(_default_cargo_labels), std::end(_default_cargo_labels), [&label](const CargoLabel &cl) {
|
||||
return cl == label;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,11 +191,11 @@ SpriteID CargoSpec::GetCargoIcon() const
|
|||
}
|
||||
|
||||
std::array<uint8_t, NUM_CARGO> _sorted_cargo_types; ///< Sort order of cargoes by cargo type.
|
||||
std::vector<const CargoSpec *> _sorted_cargo_specs; ///< Cargo specifications sorted alphabetically by name.
|
||||
std::vector<const CargoSpec *> _sorted_cargo_specs; ///< Cargo specifications sorted alphabetically by name.
|
||||
std::span<const CargoSpec *> _sorted_standard_cargo_specs; ///< Standard cargo specifications sorted alphabetically by name.
|
||||
|
||||
/** Sort cargo specifications by their name. */
|
||||
static bool CargoSpecNameSorter(const CargoSpec * const &a, const CargoSpec * const &b)
|
||||
static bool CargoSpecNameSorter(const CargoSpec *const &a, const CargoSpec *const &b)
|
||||
{
|
||||
std::string a_name = GetString(a->name);
|
||||
std::string b_name = GetString(b->name);
|
||||
|
@ -203,7 +207,7 @@ static bool CargoSpecNameSorter(const CargoSpec * const &a, const CargoSpec * co
|
|||
}
|
||||
|
||||
/** Sort cargo specifications by their cargo class. */
|
||||
static bool CargoSpecClassSorter(const CargoSpec * const &a, const CargoSpec * const &b)
|
||||
static bool CargoSpecClassSorter(const CargoSpec *const &a, const CargoSpec *const &b)
|
||||
{
|
||||
int res = b->classes.Test(CargoClass::Passengers) - a->classes.Test(CargoClass::Passengers);
|
||||
if (res == 0) {
|
||||
|
@ -249,7 +253,7 @@ void InitializeSortedCargoSpecs()
|
|||
}
|
||||
|
||||
/* _sorted_standard_cargo_specs is a subset of _sorted_cargo_specs. */
|
||||
_sorted_standard_cargo_specs = { _sorted_cargo_specs.data(), nb_standard_cargo };
|
||||
_sorted_standard_cargo_specs = {_sorted_cargo_specs.data(), nb_standard_cargo};
|
||||
}
|
||||
|
||||
uint64_t CargoSpec::WeightOfNUnitsInTrain(uint32_t n) const
|
||||
|
|
116
src/cargotype.h
116
src/cargotype.h
|
@ -10,13 +10,13 @@
|
|||
#ifndef CARGOTYPE_H
|
||||
#define CARGOTYPE_H
|
||||
|
||||
#include "economy_type.h"
|
||||
#include "core/bitmath_func.hpp"
|
||||
#include "cargo_type.h"
|
||||
#include "economy_type.h"
|
||||
#include "gfx_type.h"
|
||||
#include "landscape_type.h"
|
||||
#include "newgrf_callbacks.h"
|
||||
#include "strings_type.h"
|
||||
#include "landscape_type.h"
|
||||
#include "core/bitmath_func.hpp"
|
||||
|
||||
/** Town growth effect when delivering cargo. */
|
||||
enum TownAcceptanceEffect : uint8_t {
|
||||
|
@ -47,22 +47,22 @@ enum TownProductionEffect : uint8_t {
|
|||
|
||||
/** Cargo classes. */
|
||||
enum class CargoClass : uint8_t {
|
||||
Passengers = 0, ///< Passengers
|
||||
Mail = 1, ///< Mail
|
||||
Express = 2, ///< Express cargo (Goods, Food, Candy, but also possible for passengers)
|
||||
Armoured = 3, ///< Armoured cargo (Valuables, Gold, Diamonds)
|
||||
Bulk = 4, ///< Bulk cargo (Coal, Grain etc., Ores, Fruit)
|
||||
PieceGoods = 5, ///< Piece goods (Livestock, Wood, Steel, Paper)
|
||||
Liquid = 6, ///< Liquids (Oil, Water, Rubber)
|
||||
Refrigerated = 7, ///< Refrigerated cargo (Food, Fruit)
|
||||
Hazardous = 8, ///< Hazardous cargo (Nuclear Fuel, Explosives, etc.)
|
||||
Covered = 9, ///< Covered/Sheltered Freight (Transportation in Box Vans, Silo Wagons, etc.)
|
||||
Oversized = 10, ///< Oversized (stake/flatbed wagon)
|
||||
Powderized = 11, ///< Powderized, moist protected (powder/silo wagon)
|
||||
NotPourable = 12, ///< Not Pourable (open wagon, but not hopper wagon)
|
||||
Potable = 13, ///< Potable / food / clean.
|
||||
NonPotable = 14, ///< Non-potable / non-food / dirty.
|
||||
Special = 15, ///< Special bit used for livery refit tricks instead of normal cargoes.
|
||||
Passengers = 0, ///< Passengers
|
||||
Mail = 1, ///< Mail
|
||||
Express = 2, ///< Express cargo (Goods, Food, Candy, but also possible for passengers)
|
||||
Armoured = 3, ///< Armoured cargo (Valuables, Gold, Diamonds)
|
||||
Bulk = 4, ///< Bulk cargo (Coal, Grain etc., Ores, Fruit)
|
||||
PieceGoods = 5, ///< Piece goods (Livestock, Wood, Steel, Paper)
|
||||
Liquid = 6, ///< Liquids (Oil, Water, Rubber)
|
||||
Refrigerated = 7, ///< Refrigerated cargo (Food, Fruit)
|
||||
Hazardous = 8, ///< Hazardous cargo (Nuclear Fuel, Explosives, etc.)
|
||||
Covered = 9, ///< Covered/Sheltered Freight (Transportation in Box Vans, Silo Wagons, etc.)
|
||||
Oversized = 10, ///< Oversized (stake/flatbed wagon)
|
||||
Powderized = 11, ///< Powderized, moist protected (powder/silo wagon)
|
||||
NotPourable = 12, ///< Not Pourable (open wagon, but not hopper wagon)
|
||||
Potable = 13, ///< Potable / food / clean.
|
||||
NonPotable = 14, ///< Non-potable / non-food / dirty.
|
||||
Special = 15, ///< Special bit used for livery refit tricks instead of normal cargoes.
|
||||
};
|
||||
using CargoClasses = EnumBitSet<CargoClass, uint16_t>;
|
||||
|
||||
|
@ -72,31 +72,31 @@ static const uint TOWN_PRODUCTION_DIVISOR = 256;
|
|||
|
||||
/** Specification of a cargo type. */
|
||||
struct CargoSpec {
|
||||
CargoLabel label; ///< Unique label of the cargo type.
|
||||
CargoLabel label; ///< Unique label of the cargo type.
|
||||
uint8_t bitnum = INVALID_CARGO_BITNUM; ///< Cargo bit number, is #INVALID_CARGO_BITNUM for a non-used spec.
|
||||
uint8_t legend_colour;
|
||||
uint8_t rating_colour;
|
||||
uint8_t weight; ///< Weight of a single unit of this cargo type in 1/16 ton (62.5 kg).
|
||||
uint8_t weight; ///< Weight of a single unit of this cargo type in 1/16 ton (62.5 kg).
|
||||
uint16_t multiplier = 0x100; ///< Capacity multiplier for vehicles. (8 fractional bits)
|
||||
CargoClasses classes; ///< Classes of this cargo type. @see CargoClass
|
||||
int32_t initial_payment; ///< Initial payment rate before inflation is applied.
|
||||
int32_t initial_payment; ///< Initial payment rate before inflation is applied.
|
||||
uint8_t transit_periods[2];
|
||||
|
||||
bool is_freight; ///< Cargo type is considered to be freight (affects train freight multiplier).
|
||||
bool is_freight; ///< Cargo type is considered to be freight (affects train freight multiplier).
|
||||
TownAcceptanceEffect town_acceptance_effect; ///< The effect that delivering this cargo type has on towns. Also affects destination of subsidies.
|
||||
TownProductionEffect town_production_effect = INVALID_TPE; ///< The effect on town cargo production.
|
||||
uint16_t town_production_multiplier = TOWN_PRODUCTION_DIVISOR; ///< Town production multiplier, if commanded by TownProductionEffect.
|
||||
CargoCallbackMasks callback_mask; ///< Bitmask of cargo callbacks that have to be called
|
||||
CargoCallbackMasks callback_mask; ///< Bitmask of cargo callbacks that have to be called
|
||||
|
||||
StringID name; ///< Name of this type of cargo.
|
||||
StringID name_single; ///< Name of a single entity of this type of cargo.
|
||||
StringID units_volume; ///< Name of a single unit of cargo of this type.
|
||||
StringID quantifier; ///< Text for multiple units of cargo of this type.
|
||||
StringID abbrev; ///< Two letter abbreviation for this cargo type.
|
||||
StringID name; ///< Name of this type of cargo.
|
||||
StringID name_single; ///< Name of a single entity of this type of cargo.
|
||||
StringID units_volume; ///< Name of a single unit of cargo of this type.
|
||||
StringID quantifier; ///< Text for multiple units of cargo of this type.
|
||||
StringID abbrev; ///< Two letter abbreviation for this cargo type.
|
||||
|
||||
SpriteID sprite; ///< Icon to display this cargo type, may be \c 0xFFF (which means to resolve an action123 chain).
|
||||
SpriteID sprite; ///< Icon to display this cargo type, may be \c 0xFFF (which means to resolve an action123 chain).
|
||||
|
||||
const struct GRFFile *grffile; ///< NewGRF where #group belongs to.
|
||||
const struct GRFFile *grffile; ///< NewGRF where #group belongs to.
|
||||
const struct SpriteGroup *group;
|
||||
|
||||
Money current_payment;
|
||||
|
@ -164,13 +164,30 @@ struct CargoSpec {
|
|||
this->ValidateIndex();
|
||||
};
|
||||
|
||||
bool operator==(const Iterator &other) const { return this->index == other.index; }
|
||||
CargoSpec * operator*() const { return CargoSpec::Get(this->index); }
|
||||
Iterator & operator++() { this->index++; this->ValidateIndex(); return *this; }
|
||||
bool operator==(const Iterator &other) const
|
||||
{
|
||||
return this->index == other.index;
|
||||
}
|
||||
|
||||
CargoSpec *operator*() const
|
||||
{
|
||||
return CargoSpec::Get(this->index);
|
||||
}
|
||||
|
||||
Iterator &operator++()
|
||||
{
|
||||
this->index++;
|
||||
this->ValidateIndex();
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t index;
|
||||
void ValidateIndex() { while (this->index < CargoSpec::GetArraySize() && !(CargoSpec::Get(this->index)->IsValid())) this->index++; }
|
||||
|
||||
void ValidateIndex()
|
||||
{
|
||||
while (this->index < CargoSpec::GetArraySize() && !(CargoSpec::Get(this->index)->IsValid())) this->index++;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -178,10 +195,23 @@ struct CargoSpec {
|
|||
*/
|
||||
struct IterateWrapper {
|
||||
size_t from;
|
||||
|
||||
IterateWrapper(size_t from = 0) : from(from) {}
|
||||
Iterator begin() { return Iterator(this->from); }
|
||||
Iterator end() { return Iterator(CargoSpec::GetArraySize()); }
|
||||
bool empty() { return this->begin() == this->end(); }
|
||||
|
||||
Iterator begin()
|
||||
{
|
||||
return Iterator(this->from);
|
||||
}
|
||||
|
||||
Iterator end()
|
||||
{
|
||||
return Iterator(CargoSpec::GetArraySize());
|
||||
}
|
||||
|
||||
bool empty()
|
||||
{
|
||||
return this->begin() == this->end();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -189,7 +219,10 @@ struct CargoSpec {
|
|||
* @param from index of the first CargoSpec to consider
|
||||
* @return an iterable ensemble of all valid CargoSpec
|
||||
*/
|
||||
static IterateWrapper Iterate(size_t from = 0) { return IterateWrapper(from); }
|
||||
static IterateWrapper Iterate(size_t from = 0)
|
||||
{
|
||||
return IterateWrapper(from);
|
||||
}
|
||||
|
||||
/** List of cargo specs for each Town Product Effect. */
|
||||
static std::array<std::vector<const CargoSpec *>, NUM_TPE> town_production_cargoes;
|
||||
|
@ -242,7 +275,10 @@ using SetCargoBitIterator = SetBitIterator<CargoType, CargoTypes>;
|
|||
|
||||
/** Comparator to sort CargoType by according to desired order. */
|
||||
struct CargoTypeComparator {
|
||||
bool operator() (const CargoType &lhs, const CargoType &rhs) const { return _sorted_cargo_types[lhs] < _sorted_cargo_types[rhs]; }
|
||||
bool operator()(const CargoType &lhs, const CargoType &rhs) const
|
||||
{
|
||||
return _sorted_cargo_types[lhs] < _sorted_cargo_types[rhs];
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* CARGOTYPE_H */
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
/** @file cheat.cpp Handling (loading/saving/initializing) of cheats. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "cheat_type.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
|
|
@ -14,5 +14,4 @@
|
|||
|
||||
void ShowCheatWindow();
|
||||
|
||||
|
||||
#endif /* CHEAT_FUNC_H */
|
||||
|
|
|
@ -8,42 +8,41 @@
|
|||
/** @file cheat_gui.cpp GUI related to cheating. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "command_func.h"
|
||||
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "cheat_type.h"
|
||||
#include "command_func.h"
|
||||
#include "company_base.h"
|
||||
#include "company_func.h"
|
||||
#include "currency.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "vehicle_base.h"
|
||||
#include "textbuf_gui.h"
|
||||
#include "window_gui.h"
|
||||
#include "string_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "window_func.h"
|
||||
#include "rail_gui.h"
|
||||
#include "settings_gui.h"
|
||||
#include "company_gui.h"
|
||||
#include "currency.h"
|
||||
#include "error.h"
|
||||
#include "linkgraph/linkgraphschedule.h"
|
||||
#include "map_func.h"
|
||||
#include "tile_map.h"
|
||||
#include "newgrf.h"
|
||||
#include "error.h"
|
||||
#include "misc_cmd.h"
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "settings_type.h"
|
||||
#include "newgrf.h"
|
||||
#include "rail_gui.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "settings_gui.h"
|
||||
#include "settings_internal.h"
|
||||
#include "settings_type.h"
|
||||
#include "string_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "textbuf_gui.h"
|
||||
#include "tile_map.h"
|
||||
#include "timer/timer.h"
|
||||
#include "timer/timer_game_calendar.h"
|
||||
#include "timer/timer_game_economy.h"
|
||||
#include "vehicle_base.h"
|
||||
#include "window_func.h"
|
||||
#include "window_gui.h"
|
||||
|
||||
#include "widgets/cheat_widget.h"
|
||||
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
||||
/**
|
||||
* The 'amount' to cheat with.
|
||||
* This variable is semantically a constant value, but because the cheat
|
||||
|
@ -170,17 +169,17 @@ static int32_t ClickChangeMaxHlCheat(int32_t new_value, int32_t)
|
|||
|
||||
/** Available cheats. */
|
||||
enum CheatNumbers : uint8_t {
|
||||
CHT_MONEY, ///< Change amount of money.
|
||||
CHT_CHANGE_COMPANY, ///< Switch company.
|
||||
CHT_EXTRA_DYNAMITE, ///< Dynamite anything.
|
||||
CHT_MONEY, ///< Change amount of money.
|
||||
CHT_CHANGE_COMPANY, ///< Switch company.
|
||||
CHT_EXTRA_DYNAMITE, ///< Dynamite anything.
|
||||
CHT_CROSSINGTUNNELS, ///< Allow tunnels to cross each other.
|
||||
CHT_NO_JETCRASH, ///< Disable jet-airplane crashes.
|
||||
CHT_SETUP_PROD, ///< Allow manually editing of industry production.
|
||||
CHT_STATION_RATING, ///< Fix station ratings at 100%.
|
||||
CHT_EDIT_MAX_HL, ///< Edit maximum allowed heightlevel
|
||||
CHT_CHANGE_DATE, ///< Do time traveling.
|
||||
CHT_NO_JETCRASH, ///< Disable jet-airplane crashes.
|
||||
CHT_SETUP_PROD, ///< Allow manually editing of industry production.
|
||||
CHT_STATION_RATING, ///< Fix station ratings at 100%.
|
||||
CHT_EDIT_MAX_HL, ///< Edit maximum allowed heightlevel
|
||||
CHT_CHANGE_DATE, ///< Do time traveling.
|
||||
|
||||
CHT_NUM_CHEATS, ///< Number of cheats.
|
||||
CHT_NUM_CHEATS, ///< Number of cheats.
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -192,11 +191,11 @@ typedef int32_t CheckButtonClick(int32_t new_value, int32_t change_direction);
|
|||
|
||||
/** Information of a cheat. */
|
||||
struct CheatEntry {
|
||||
VarType type; ///< type of selector
|
||||
StringID str; ///< string with descriptive text
|
||||
void *variable; ///< pointer to the variable
|
||||
bool *been_used; ///< has this cheat been used before?
|
||||
CheckButtonClick *proc;///< procedure
|
||||
VarType type; ///< type of selector
|
||||
StringID str; ///< string with descriptive text
|
||||
void *variable; ///< pointer to the variable
|
||||
bool *been_used; ///< has this cheat been used before?
|
||||
CheckButtonClick *proc; ///< procedure
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -204,15 +203,15 @@ struct CheatEntry {
|
|||
* Order matches with the values of #CheatNumbers
|
||||
*/
|
||||
static const CheatEntry _cheats_ui[] = {
|
||||
{SLE_INT32, STR_CHEAT_MONEY, &_money_cheat_amount, &_cheats.money.been_used, &ClickMoneyCheat },
|
||||
{SLE_UINT8, STR_CHEAT_CHANGE_COMPANY, &_local_company, &_cheats.switch_company.been_used, &ClickChangeCompanyCheat },
|
||||
{SLE_BOOL, STR_CHEAT_EXTRA_DYNAMITE, &_cheats.magic_bulldozer.value, &_cheats.magic_bulldozer.been_used, nullptr },
|
||||
{SLE_BOOL, STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value, &_cheats.crossing_tunnels.been_used, nullptr },
|
||||
{SLE_BOOL, STR_CHEAT_NO_JETCRASH, &_cheats.no_jetcrash.value, &_cheats.no_jetcrash.been_used, nullptr },
|
||||
{SLE_BOOL, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, &ClickSetProdCheat },
|
||||
{SLE_BOOL, STR_CHEAT_STATION_RATING, &_cheats.station_rating.value, &_cheats.station_rating.been_used, nullptr },
|
||||
{SLE_UINT8, STR_CHEAT_EDIT_MAX_HL, &_settings_game.construction.map_height_limit, &_cheats.edit_max_hl.been_used, &ClickChangeMaxHlCheat },
|
||||
{SLE_INT32, STR_CHEAT_CHANGE_DATE, &TimerGameCalendar::year, &_cheats.change_date.been_used, &ClickChangeDateCheat },
|
||||
{SLE_INT32, STR_CHEAT_MONEY, &_money_cheat_amount, &_cheats.money.been_used, &ClickMoneyCheat},
|
||||
{SLE_UINT8, STR_CHEAT_CHANGE_COMPANY, &_local_company, &_cheats.switch_company.been_used, &ClickChangeCompanyCheat},
|
||||
{SLE_BOOL, STR_CHEAT_EXTRA_DYNAMITE, &_cheats.magic_bulldozer.value, &_cheats.magic_bulldozer.been_used, nullptr},
|
||||
{SLE_BOOL, STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value, &_cheats.crossing_tunnels.been_used, nullptr},
|
||||
{SLE_BOOL, STR_CHEAT_NO_JETCRASH, &_cheats.no_jetcrash.value, &_cheats.no_jetcrash.been_used, nullptr},
|
||||
{SLE_BOOL, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, &ClickSetProdCheat},
|
||||
{SLE_BOOL, STR_CHEAT_STATION_RATING, &_cheats.station_rating.value, &_cheats.station_rating.been_used, nullptr},
|
||||
{SLE_UINT8, STR_CHEAT_EDIT_MAX_HL, &_settings_game.construction.map_height_limit, &_cheats.edit_max_hl.been_used, &ClickChangeMaxHlCheat},
|
||||
{SLE_INT32, STR_CHEAT_CHANGE_DATE, &TimerGameCalendar::year, &_cheats.change_date.been_used, &ClickChangeDateCheat},
|
||||
};
|
||||
|
||||
static_assert(CHT_NUM_CHEATS == lengthof(_cheats_ui));
|
||||
|
@ -249,7 +248,9 @@ struct CheatWindow : Window {
|
|||
|
||||
CheatWindow(WindowDesc &desc) : Window(desc)
|
||||
{
|
||||
this->sandbox_settings = GetFilteredSettingCollection([](const SettingDesc &sd) { return sd.flags.Test(SettingFlag::Sandbox); });
|
||||
this->sandbox_settings = GetFilteredSettingCollection([](const SettingDesc &sd) {
|
||||
return sd.flags.Test(SettingFlag::Sandbox);
|
||||
});
|
||||
this->InitNested();
|
||||
}
|
||||
|
||||
|
@ -261,8 +262,12 @@ struct CheatWindow : Window {
|
|||
void DrawWidget(const Rect &r, WidgetID widget) const override
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_C_PANEL: DrawCheatWidget(r); break;
|
||||
case WID_C_SETTINGS: DrawSettingsWidget(r); break;
|
||||
case WID_C_PANEL:
|
||||
DrawCheatWidget(r);
|
||||
break;
|
||||
case WID_C_SETTINGS:
|
||||
DrawSettingsWidget(r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,8 +278,8 @@ struct CheatWindow : Window {
|
|||
|
||||
bool rtl = _current_text_dir == TD_RTL;
|
||||
uint button_left = rtl ? ir.right - SETTING_BUTTON_WIDTH : ir.left;
|
||||
uint text_left = ir.left + (rtl ? 0 : WidgetDimensions::scaled.hsep_wide + SETTING_BUTTON_WIDTH);
|
||||
uint text_right = ir.right - (rtl ? WidgetDimensions::scaled.hsep_wide + SETTING_BUTTON_WIDTH : 0);
|
||||
uint text_left = ir.left + (rtl ? 0 : WidgetDimensions::scaled.hsep_wide + SETTING_BUTTON_WIDTH);
|
||||
uint text_right = ir.right - (rtl ? WidgetDimensions::scaled.hsep_wide + SETTING_BUTTON_WIDTH : 0);
|
||||
|
||||
int text_y_offset = (this->line_height - GetCharacterHeight(FS_NORMAL)) / 2;
|
||||
int button_y_offset = (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
|
||||
|
@ -286,7 +291,7 @@ struct CheatWindow : Window {
|
|||
std::string str;
|
||||
switch (ce->type) {
|
||||
case SLE_BOOL: {
|
||||
bool on = (*(bool*)ce->variable);
|
||||
bool on = (*(bool *)ce->variable);
|
||||
|
||||
DrawBoolButton(button_left, y + button_y_offset, COLOUR_YELLOW, COLOUR_GREY, on, true);
|
||||
str = GetString(ce->str, on ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
|
||||
|
@ -362,8 +367,8 @@ struct CheatWindow : Window {
|
|||
DrawDropDownButton(buttons.left, buttons.top, COLOUR_YELLOW, state != 0, editable);
|
||||
} else {
|
||||
/* Draw [<][>] boxes for settings of an integer-type */
|
||||
DrawArrowButtons(buttons.left, buttons.top, COLOUR_YELLOW, state,
|
||||
editable && value != (sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val), editable && static_cast<uint32_t>(value) != max_val);
|
||||
DrawArrowButtons(buttons.left, buttons.top, COLOUR_YELLOW, state, editable && value != (sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val),
|
||||
editable && static_cast<uint32_t>(value) != max_val);
|
||||
}
|
||||
auto [param1, param2] = sd->GetValueParams(value);
|
||||
DrawString(text.left, text.right, text.top, GetString(sd->GetTitle(), STR_CONFIG_SETTING_VALUE, param1, param2), TC_LIGHT_BLUE);
|
||||
|
@ -372,8 +377,12 @@ struct CheatWindow : Window {
|
|||
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_C_PANEL: UpdateCheatPanelSize(size); break;
|
||||
case WID_C_SETTINGS: UpdateSettingsPanelSize(size); break;
|
||||
case WID_C_PANEL:
|
||||
UpdateCheatPanelSize(size);
|
||||
break;
|
||||
case WID_C_SETTINGS:
|
||||
UpdateSettingsPanelSize(size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -431,8 +440,12 @@ struct CheatWindow : Window {
|
|||
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_C_PANEL: CheatPanelClick(pt); break;
|
||||
case WID_C_SETTINGS: SettingsPanelClick(pt); break;
|
||||
case WID_C_PANEL:
|
||||
CheatPanelClick(pt);
|
||||
break;
|
||||
case WID_C_SETTINGS:
|
||||
SettingsPanelClick(pt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -566,7 +579,7 @@ struct CheatWindow : Window {
|
|||
if (value != oldvalue) {
|
||||
this->last_clicked_setting = nullptr;
|
||||
this->clicked_setting = sd;
|
||||
this->clicked = (x >= SETTING_BUTTON_WIDTH / 2) != (_current_text_dir == TD_RTL) ? 2 : 1;
|
||||
this->clicked = (x >= SETTING_BUTTON_WIDTH / 2) != (_current_text_dir == TD_RTL) ? 2 : 1;
|
||||
this->SetTimeout();
|
||||
_left_button_clicked = false;
|
||||
}
|
||||
|
@ -635,17 +648,12 @@ struct CheatWindow : Window {
|
|||
}
|
||||
|
||||
IntervalTimer<TimerGameCalendar> daily_interval = {{TimerGameCalendar::MONTH, TimerGameCalendar::Priority::NONE}, [this](auto) {
|
||||
this->SetDirty();
|
||||
}};
|
||||
this->SetDirty();
|
||||
}};
|
||||
};
|
||||
|
||||
/** Window description of the cheats GUI. */
|
||||
static WindowDesc _cheats_desc(
|
||||
WDP_AUTO, "cheats", 0, 0,
|
||||
WC_CHEATS, WC_NONE,
|
||||
{},
|
||||
_nested_cheat_widgets
|
||||
);
|
||||
static WindowDesc _cheats_desc(WDP_AUTO, "cheats", 0, 0, WC_CHEATS, WC_NONE, {}, _nested_cheat_widgets);
|
||||
|
||||
/** Open cheat window. */
|
||||
void ShowCheatWindow()
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
struct Cheat {
|
||||
bool been_used; ///< has this cheat been used before?
|
||||
bool value; ///< tells if the bool cheat is active or not
|
||||
bool value; ///< tells if the bool cheat is active or not
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -24,15 +24,16 @@ struct Cheat {
|
|||
* Only add new entries at the end of the struct!
|
||||
*/
|
||||
struct Cheats {
|
||||
Cheat magic_bulldozer; ///< dynamite industries, objects
|
||||
Cheat switch_company; ///< change to another company
|
||||
Cheat money; ///< get rich or poor
|
||||
Cheat magic_bulldozer; ///< dynamite industries, objects
|
||||
Cheat switch_company; ///< change to another company
|
||||
Cheat money; ///< get rich or poor
|
||||
Cheat crossing_tunnels; ///< allow tunnels that cross each other
|
||||
Cheat no_jetcrash; ///< no jet will crash on small airports anymore
|
||||
Cheat change_date; ///< changes date ingame
|
||||
Cheat setup_prod; ///< setup raw-material production in game
|
||||
Cheat edit_max_hl; ///< edit the maximum heightlevel; this is a cheat because of the fact that it needs to reset NewGRF game state and doing so as a simple configuration breaks the expectation of many
|
||||
Cheat station_rating; ///< Fix station ratings at 100%
|
||||
Cheat no_jetcrash; ///< no jet will crash on small airports anymore
|
||||
Cheat change_date; ///< changes date ingame
|
||||
Cheat setup_prod; ///< setup raw-material production in game
|
||||
Cheat
|
||||
edit_max_hl; ///< edit the maximum heightlevel; this is a cheat because of the fact that it needs to reset NewGRF game state and doing so as a simple configuration breaks the expectation of many
|
||||
Cheat station_rating; ///< Fix station ratings at 100%
|
||||
};
|
||||
|
||||
extern Cheats _cheats;
|
||||
|
|
|
@ -8,18 +8,19 @@
|
|||
/** @file clear_cmd.cpp Commands related to clear tiles. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "core/random_func.hpp"
|
||||
#include "clear_map.h"
|
||||
#include "command_func.h"
|
||||
#include "landscape.h"
|
||||
#include "genworld.h"
|
||||
#include "viewport_func.h"
|
||||
#include "core/random_func.hpp"
|
||||
#include "newgrf_generic.h"
|
||||
#include "landscape.h"
|
||||
#include "landscape_cmd.h"
|
||||
#include "newgrf_generic.h"
|
||||
#include "viewport_func.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/sprites.h"
|
||||
#include "table/clear_land.h"
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
@ -119,7 +120,8 @@ static void DrawTile_Clear(TileInfo *ti)
|
|||
break;
|
||||
|
||||
case CLEAR_ROCKS:
|
||||
DrawGroundSprite((HasGrfMiscBit(GrfMiscBit::SecondRockyTileSet) && (TileHash(ti->x, ti->y) & 1) ? SPR_FLAT_ROCKY_LAND_2 : SPR_FLAT_ROCKY_LAND_1) + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
|
||||
DrawGroundSprite(
|
||||
(HasGrfMiscBit(GrfMiscBit::SecondRockyTileSet) && (TileHash(ti->x, ti->y) & 1) ? SPR_FLAT_ROCKY_LAND_2 : SPR_FLAT_ROCKY_LAND_1) + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
|
||||
break;
|
||||
|
||||
case CLEAR_FIELDS:
|
||||
|
@ -174,7 +176,6 @@ static void UpdateFences(TileIndex tile)
|
|||
if (dirty) MarkTileDirtyByTile(tile);
|
||||
}
|
||||
|
||||
|
||||
/** Convert to or from snowy tiles. */
|
||||
static void TileLoopClearAlps(TileIndex tile)
|
||||
{
|
||||
|
@ -251,9 +252,14 @@ static void TileLoop_Clear(TileIndex tile)
|
|||
AmbientSoundEffect(tile);
|
||||
|
||||
switch (_settings_game.game_creation.landscape) {
|
||||
case LandscapeType::Tropic: TileLoopClearDesert(tile); break;
|
||||
case LandscapeType::Arctic: TileLoopClearAlps(tile); break;
|
||||
default: break;
|
||||
case LandscapeType::Tropic:
|
||||
TileLoopClearDesert(tile);
|
||||
break;
|
||||
case LandscapeType::Arctic:
|
||||
TileLoopClearAlps(tile);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (IsSnowTile(tile)) return;
|
||||
|
@ -340,7 +346,7 @@ void GenerateClearTile()
|
|||
} while (!IsTileType(tile_new, MP_CLEAR) || IsClearGround(tile_new, CLEAR_DESERT));
|
||||
tile = tile_new;
|
||||
}
|
||||
get_out:;
|
||||
get_out:;
|
||||
}
|
||||
} while (--i);
|
||||
}
|
||||
|
@ -354,12 +360,12 @@ static void GetTileDesc_Clear(TileIndex tile, TileDesc &td)
|
|||
{
|
||||
/* Each pair holds a normal and a snowy ClearGround description. */
|
||||
static constexpr std::pair<StringID, StringID> clear_land_str[] = {
|
||||
{STR_LAI_CLEAR_DESCRIPTION_GRASS, STR_LAI_CLEAR_DESCRIPTION_SNOWY_GRASS},
|
||||
{STR_LAI_CLEAR_DESCRIPTION_GRASS, STR_LAI_CLEAR_DESCRIPTION_SNOWY_GRASS},
|
||||
{STR_LAI_CLEAR_DESCRIPTION_ROUGH_LAND, STR_LAI_CLEAR_DESCRIPTION_SNOWY_ROUGH_LAND},
|
||||
{STR_LAI_CLEAR_DESCRIPTION_ROCKS, STR_LAI_CLEAR_DESCRIPTION_SNOWY_ROCKS},
|
||||
{STR_LAI_CLEAR_DESCRIPTION_FIELDS, STR_EMPTY},
|
||||
{STR_EMPTY, STR_EMPTY}, // CLEAR_SNOW does not appear in the map.
|
||||
{STR_LAI_CLEAR_DESCRIPTION_DESERT, STR_EMPTY},
|
||||
{STR_LAI_CLEAR_DESCRIPTION_ROCKS, STR_LAI_CLEAR_DESCRIPTION_SNOWY_ROCKS},
|
||||
{STR_LAI_CLEAR_DESCRIPTION_FIELDS, STR_EMPTY},
|
||||
{STR_EMPTY, STR_EMPTY}, // CLEAR_SNOW does not appear in the map.
|
||||
{STR_LAI_CLEAR_DESCRIPTION_DESERT, STR_EMPTY},
|
||||
};
|
||||
|
||||
if (!IsSnowTile(tile) && IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) == 0) {
|
||||
|
@ -382,18 +388,18 @@ static CommandCost TerraformTile_Clear(TileIndex tile, DoCommandFlags flags, int
|
|||
}
|
||||
|
||||
extern const TileTypeProcs _tile_type_clear_procs = {
|
||||
DrawTile_Clear, ///< draw_tile_proc
|
||||
GetSlopePixelZ_Clear, ///< get_slope_z_proc
|
||||
ClearTile_Clear, ///< clear_tile_proc
|
||||
nullptr, ///< add_accepted_cargo_proc
|
||||
GetTileDesc_Clear, ///< get_tile_desc_proc
|
||||
DrawTile_Clear, ///< draw_tile_proc
|
||||
GetSlopePixelZ_Clear, ///< get_slope_z_proc
|
||||
ClearTile_Clear, ///< clear_tile_proc
|
||||
nullptr, ///< add_accepted_cargo_proc
|
||||
GetTileDesc_Clear, ///< get_tile_desc_proc
|
||||
GetTileTrackStatus_Clear, ///< get_tile_track_status_proc
|
||||
nullptr, ///< click_tile_proc
|
||||
nullptr, ///< animate_tile_proc
|
||||
TileLoop_Clear, ///< tile_loop_proc
|
||||
ChangeTileOwner_Clear, ///< change_tile_owner_proc
|
||||
nullptr, ///< add_produced_cargo_proc
|
||||
nullptr, ///< vehicle_enter_tile_proc
|
||||
GetFoundation_Clear, ///< get_foundation_proc
|
||||
TerraformTile_Clear, ///< terraform_tile_proc
|
||||
nullptr, ///< click_tile_proc
|
||||
nullptr, ///< animate_tile_proc
|
||||
TileLoop_Clear, ///< tile_loop_proc
|
||||
ChangeTileOwner_Clear, ///< change_tile_owner_proc
|
||||
nullptr, ///< add_produced_cargo_proc
|
||||
nullptr, ///< vehicle_enter_tile_proc
|
||||
GetFoundation_Clear, ///< get_foundation_proc
|
||||
TerraformTile_Clear, ///< terraform_tile_proc
|
||||
};
|
||||
|
|
|
@ -17,15 +17,14 @@
|
|||
* Ground types. Valid densities in comments after the enum.
|
||||
*/
|
||||
enum ClearGround : uint8_t {
|
||||
CLEAR_GRASS = 0, ///< 0-3
|
||||
CLEAR_ROUGH = 1, ///< 3
|
||||
CLEAR_ROCKS = 2, ///< 3
|
||||
CLEAR_GRASS = 0, ///< 0-3
|
||||
CLEAR_ROUGH = 1, ///< 3
|
||||
CLEAR_ROCKS = 2, ///< 3
|
||||
CLEAR_FIELDS = 3, ///< 3
|
||||
CLEAR_SNOW = 4, ///< 0-3 (Not stored in map.)
|
||||
CLEAR_SNOW = 4, ///< 0-3 (Not stored in map.)
|
||||
CLEAR_DESERT = 5, ///< 1,3
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Test if a tile is covered with snow.
|
||||
* @param t the tile to check
|
||||
|
@ -61,7 +60,6 @@ inline bool IsClearGround(Tile t, ClearGround ct)
|
|||
return GetClearGround(t) == ct;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the density of a non-field clear tile.
|
||||
* @param t the tile to get the density of
|
||||
|
@ -98,7 +96,6 @@ inline void SetClearDensity(Tile t, uint d)
|
|||
SB(t.m5(), 0, 2, d);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the counter used to advance to the next clear density/field type.
|
||||
* @param t the tile to get the counter of
|
||||
|
@ -135,7 +132,6 @@ inline void SetClearCounter(Tile t, uint c)
|
|||
SB(t.m5(), 5, 3, c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets ground type and density in one go, also sets the counter to 0
|
||||
* @param t the tile to set the ground type and density for
|
||||
|
@ -149,7 +145,6 @@ inline void SetClearGroundDensity(Tile t, ClearGround type, uint density)
|
|||
t.m5() = 0 << 5 | type << 2 | density;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the field type (production stage) of the field
|
||||
* @param t the field to get the type of
|
||||
|
@ -183,7 +178,7 @@ inline void SetFieldType(Tile t, uint f)
|
|||
inline IndustryID GetIndustryIndexOfField(Tile t)
|
||||
{
|
||||
assert(GetClearGround(t) == CLEAR_FIELDS);
|
||||
return(IndustryID) t.m2();
|
||||
return (IndustryID)t.m2();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -198,7 +193,6 @@ inline void SetIndustryIndexOfField(Tile t, IndustryID i)
|
|||
t.m2() = i.base();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is there a fence at the given border?
|
||||
* @param t the tile to check for fences
|
||||
|
@ -210,11 +204,16 @@ inline uint GetFence(Tile t, DiagDirection side)
|
|||
{
|
||||
assert(IsClearGround(t, CLEAR_FIELDS));
|
||||
switch (side) {
|
||||
default: NOT_REACHED();
|
||||
case DIAGDIR_SE: return GB(t.m4(), 2, 3);
|
||||
case DIAGDIR_SW: return GB(t.m4(), 5, 3);
|
||||
case DIAGDIR_NE: return GB(t.m3(), 5, 3);
|
||||
case DIAGDIR_NW: return GB(t.m6(), 2, 3);
|
||||
default:
|
||||
NOT_REACHED();
|
||||
case DIAGDIR_SE:
|
||||
return GB(t.m4(), 2, 3);
|
||||
case DIAGDIR_SW:
|
||||
return GB(t.m4(), 5, 3);
|
||||
case DIAGDIR_NE:
|
||||
return GB(t.m3(), 5, 3);
|
||||
case DIAGDIR_NW:
|
||||
return GB(t.m6(), 2, 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,15 +228,23 @@ inline void SetFence(Tile t, DiagDirection side, uint h)
|
|||
{
|
||||
assert(IsClearGround(t, CLEAR_FIELDS));
|
||||
switch (side) {
|
||||
default: NOT_REACHED();
|
||||
case DIAGDIR_SE: SB(t.m4(), 2, 3, h); break;
|
||||
case DIAGDIR_SW: SB(t.m4(), 5, 3, h); break;
|
||||
case DIAGDIR_NE: SB(t.m3(), 5, 3, h); break;
|
||||
case DIAGDIR_NW: SB(t.m6(), 2, 3, h); break;
|
||||
default:
|
||||
NOT_REACHED();
|
||||
case DIAGDIR_SE:
|
||||
SB(t.m4(), 2, 3, h);
|
||||
break;
|
||||
case DIAGDIR_SW:
|
||||
SB(t.m4(), 5, 3, h);
|
||||
break;
|
||||
case DIAGDIR_NE:
|
||||
SB(t.m3(), 5, 3, h);
|
||||
break;
|
||||
case DIAGDIR_NW:
|
||||
SB(t.m6(), 2, 3, h);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a clear tile.
|
||||
* @param t the tile to make a clear tile
|
||||
|
@ -258,7 +265,6 @@ inline void MakeClear(Tile t, ClearGround g, uint density)
|
|||
t.m8() = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a (farm) field tile.
|
||||
* @param t the tile to make a farm field
|
||||
|
|
|
@ -8,46 +8,49 @@
|
|||
/** @file command.cpp Handling of commands. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "landscape.h"
|
||||
#include "error.h"
|
||||
#include "gui.h"
|
||||
#include "command_func.h"
|
||||
#include "network/network_type.h"
|
||||
#include "network/network.h"
|
||||
#include "genworld.h"
|
||||
#include "strings_func.h"
|
||||
#include "texteff.hpp"
|
||||
#include "town.h"
|
||||
#include "timer/timer_game_economy.h"
|
||||
#include "company_func.h"
|
||||
#include "company_base.h"
|
||||
#include "signal_func.h"
|
||||
|
||||
#include "core/backup_type.hpp"
|
||||
#include "object_base.h"
|
||||
#include "autoreplace_cmd.h"
|
||||
#include "command_func.h"
|
||||
#include "company_base.h"
|
||||
#include "company_cmd.h"
|
||||
#include "company_func.h"
|
||||
#include "depot_cmd.h"
|
||||
#include "economy_cmd.h"
|
||||
#include "engine_cmd.h"
|
||||
#include "error.h"
|
||||
#include "genworld.h"
|
||||
#include "goal_cmd.h"
|
||||
#include "group_cmd.h"
|
||||
#include "gui.h"
|
||||
#include "industry_cmd.h"
|
||||
#include "league_cmd.h"
|
||||
#include "landscape.h"
|
||||
#include "landscape_cmd.h"
|
||||
#include "league_cmd.h"
|
||||
#include "misc/endian_buffer.hpp"
|
||||
#include "misc_cmd.h"
|
||||
#include "network/network.h"
|
||||
#include "network/network_type.h"
|
||||
#include "news_cmd.h"
|
||||
#include "object_base.h"
|
||||
#include "object_cmd.h"
|
||||
#include "order_cmd.h"
|
||||
#include "rail_cmd.h"
|
||||
#include "road_cmd.h"
|
||||
#include "roadveh_cmd.h"
|
||||
#include "settings_cmd.h"
|
||||
#include "signal_func.h"
|
||||
#include "signs_cmd.h"
|
||||
#include "station_cmd.h"
|
||||
#include "story_cmd.h"
|
||||
#include "string_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "subsidy_cmd.h"
|
||||
#include "terraform_cmd.h"
|
||||
#include "texteff.hpp"
|
||||
#include "timer/timer_game_economy.h"
|
||||
#include "timetable_cmd.h"
|
||||
#include "town.h"
|
||||
#include "town_cmd.h"
|
||||
#include "train_cmd.h"
|
||||
#include "tree_cmd.h"
|
||||
|
@ -56,17 +59,13 @@
|
|||
#include "viewport_cmd.h"
|
||||
#include "water_cmd.h"
|
||||
#include "waypoint_cmd.h"
|
||||
#include "misc/endian_buffer.hpp"
|
||||
#include "string_func.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
||||
int RecursiveCommandCounter::_counter = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Define a command with the flags which belongs to it.
|
||||
*
|
||||
|
@ -74,17 +73,22 @@ int RecursiveCommandCounter::_counter = 0;
|
|||
* the #CommandFlag::Auto, #CommandFlag::Offline and #CommandFlag::Server values.
|
||||
*/
|
||||
struct CommandInfo {
|
||||
const char *name; ///< A human readable name for the procedure
|
||||
const char *name; ///< A human readable name for the procedure
|
||||
CommandFlags flags; ///< The (command) flags to that apply to this command
|
||||
CommandType type; ///< The type of command.
|
||||
CommandType type; ///< The type of command.
|
||||
};
|
||||
|
||||
/* Helpers to generate the master command table from the command traits. */
|
||||
template <typename T>
|
||||
inline constexpr CommandInfo CommandFromTrait() noexcept { return { T::name, T::flags, T::type }; };
|
||||
inline constexpr CommandInfo CommandFromTrait() noexcept
|
||||
{
|
||||
return {T::name, T::flags, T::type};
|
||||
};
|
||||
|
||||
template <typename T, T... i>
|
||||
inline constexpr auto MakeCommandsFromTraits(std::integer_sequence<T, i...>) noexcept {
|
||||
return std::array<CommandInfo, sizeof...(i)>{{ CommandFromTrait<CommandTraits<static_cast<Commands>(i)>>()... }};
|
||||
inline constexpr auto MakeCommandsFromTraits(std::integer_sequence<T, i...>) noexcept
|
||||
{
|
||||
return std::array<CommandInfo, sizeof...(i)>{{CommandFromTrait<CommandTraits<static_cast<Commands>(i)>>()...}};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,7 +100,6 @@ inline constexpr auto MakeCommandsFromTraits(std::integer_sequence<T, i...>) noe
|
|||
*/
|
||||
static constexpr auto _command_proc_table = MakeCommandsFromTraits(std::make_integer_sequence<std::underlying_type_t<Commands>, CMD_END>{});
|
||||
|
||||
|
||||
/**
|
||||
* This function range-checks a cmd.
|
||||
*
|
||||
|
@ -145,15 +148,15 @@ bool IsCommandAllowedWhilePaused(Commands cmd)
|
|||
{
|
||||
/* Lookup table for the command types that are allowed for a given pause level setting. */
|
||||
static const int command_type_lookup[] = {
|
||||
CMDPL_ALL_ACTIONS, ///< CMDT_LANDSCAPE_CONSTRUCTION
|
||||
CMDPL_NO_LANDSCAPING, ///< CMDT_VEHICLE_CONSTRUCTION
|
||||
CMDPL_NO_LANDSCAPING, ///< CMDT_MONEY_MANAGEMENT
|
||||
CMDPL_ALL_ACTIONS, ///< CMDT_LANDSCAPE_CONSTRUCTION
|
||||
CMDPL_NO_LANDSCAPING, ///< CMDT_VEHICLE_CONSTRUCTION
|
||||
CMDPL_NO_LANDSCAPING, ///< CMDT_MONEY_MANAGEMENT
|
||||
CMDPL_NO_CONSTRUCTION, ///< CMDT_VEHICLE_MANAGEMENT
|
||||
CMDPL_NO_CONSTRUCTION, ///< CMDT_ROUTE_MANAGEMENT
|
||||
CMDPL_NO_CONSTRUCTION, ///< CMDT_OTHER_MANAGEMENT
|
||||
CMDPL_NO_ACTIONS, ///< CMDT_COMPANY_SETTING
|
||||
CMDPL_NO_ACTIONS, ///< CMDT_SERVER_SETTING
|
||||
CMDPL_NO_ACTIONS, ///< CMDT_CHEAT
|
||||
CMDPL_NO_ACTIONS, ///< CMDT_COMPANY_SETTING
|
||||
CMDPL_NO_ACTIONS, ///< CMDT_SERVER_SETTING
|
||||
CMDPL_NO_ACTIONS, ///< CMDT_CHEAT
|
||||
};
|
||||
static_assert(lengthof(command_type_lookup) == CMDT_END);
|
||||
|
||||
|
@ -218,11 +221,10 @@ std::tuple<bool, bool, bool> CommandHelperBase::InternalPostBefore(Commands cmd,
|
|||
bool only_sending = _networking && !network_command;
|
||||
|
||||
if (_pause_mode.Any() && !IsCommandAllowedWhilePaused(cmd) && !estimate_only) {
|
||||
ShowErrorMessage(GetEncodedString(err_message), GetEncodedString(STR_ERROR_NOT_ALLOWED_WHILE_PAUSED),
|
||||
WL_INFO, TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE);
|
||||
return { true, estimate_only, only_sending };
|
||||
ShowErrorMessage(GetEncodedString(err_message), GetEncodedString(STR_ERROR_NOT_ALLOWED_WHILE_PAUSED), WL_INFO, TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE);
|
||||
return {true, estimate_only, only_sending};
|
||||
} else {
|
||||
return { false, estimate_only, only_sending };
|
||||
return {false, estimate_only, only_sending};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,7 +262,8 @@ void CommandHelperBase::InternalPostResult(CommandCost &res, TileIndex tile, boo
|
|||
/** Helper to make a desync log for a command. */
|
||||
void CommandHelperBase::LogCommandExecution(Commands cmd, StringID err_message, const CommandDataBuffer &args, bool failed)
|
||||
{
|
||||
Debug(desync, 1, "{}: {:08x}; {:02x}; {:02x}; {:08x}; {:08x}; {} ({})", failed ? "cmdf" : "cmd", (uint32_t)TimerGameEconomy::date.base(), TimerGameEconomy::date_fract, _current_company, cmd, err_message, FormatArrayAsHex(args), GetCommandName(cmd));
|
||||
Debug(desync, 1, "{}: {:08x}; {:02x}; {:02x}; {:08x}; {:08x}; {} ({})", failed ? "cmdf" : "cmd", (uint32_t)TimerGameEconomy::date.base(), TimerGameEconomy::date_fract, _current_company, cmd,
|
||||
err_message, FormatArrayAsHex(args), GetCommandName(cmd));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -299,7 +302,8 @@ bool CommandHelperBase::InternalExecutePrepTest(CommandFlags cmd_flags, TileInde
|
|||
* @param[in,out] cur_company Backup of current company at start of command execution.
|
||||
* @return True if test run can go ahead, false on error.
|
||||
*/
|
||||
std::tuple<bool, bool, bool> CommandHelperBase::InternalExecuteValidateTestAndPrepExec(CommandCost &res, CommandFlags cmd_flags, bool estimate_only, bool network_command, [[maybe_unused]] Backup<CompanyID> &cur_company)
|
||||
std::tuple<bool, bool, bool> CommandHelperBase::InternalExecuteValidateTestAndPrepExec(
|
||||
CommandCost &res, CommandFlags cmd_flags, bool estimate_only, bool network_command, [[maybe_unused]] Backup<CompanyID> &cur_company)
|
||||
{
|
||||
BasePersistentStorageArray::SwitchMode(PSM_LEAVE_TESTMODE);
|
||||
SetTownRatingTestMode(false);
|
||||
|
@ -314,7 +318,7 @@ std::tuple<bool, bool, bool> CommandHelperBase::InternalExecuteValidateTestAndPr
|
|||
* we bail out here. */
|
||||
bool test_and_exec_can_differ = cmd_flags.Test(CommandFlag::NoTest);
|
||||
if (res.Failed() || estimate_only || (!test_and_exec_can_differ && !CheckCompanyHasMoney(res))) {
|
||||
return { true, !_networking || _generating_world || network_command, false };
|
||||
return {true, !_networking || _generating_world || network_command, false};
|
||||
}
|
||||
|
||||
bool send_net = _networking && !_generating_world && !network_command;
|
||||
|
@ -325,7 +329,7 @@ std::tuple<bool, bool, bool> CommandHelperBase::InternalExecuteValidateTestAndPr
|
|||
BasePersistentStorageArray::SwitchMode(PSM_ENTER_COMMAND);
|
||||
}
|
||||
|
||||
return { false, _debug_desync_level >= 1, send_net };
|
||||
return {false, _debug_desync_level >= 1, send_net};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -339,7 +343,8 @@ std::tuple<bool, bool, bool> CommandHelperBase::InternalExecuteValidateTestAndPr
|
|||
* @param[in,out] cur_company Backup of current company at start of command execution.
|
||||
* @return Final command result.
|
||||
*/
|
||||
CommandCost CommandHelperBase::InternalExecuteProcessResult(Commands cmd, CommandFlags cmd_flags, [[maybe_unused]] const CommandCost &res_test, const CommandCost &res_exec, Money extra_cash, TileIndex tile, Backup<CompanyID> &cur_company)
|
||||
CommandCost CommandHelperBase::InternalExecuteProcessResult(
|
||||
Commands cmd, CommandFlags cmd_flags, [[maybe_unused]] const CommandCost &res_test, const CommandCost &res_exec, Money extra_cash, TileIndex tile, Backup<CompanyID> &cur_company)
|
||||
{
|
||||
BasePersistentStorageArray::SwitchMode(PSM_LEAVE_COMMAND);
|
||||
|
||||
|
@ -392,7 +397,6 @@ CommandCost CommandHelperBase::InternalExecuteProcessResult(Commands cmd, Comman
|
|||
return res_exec;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds the cost of the given command return value to this cost.
|
||||
* Also takes a possible error message when it is set.
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
#ifndef COMMAND_FUNC_H
|
||||
#define COMMAND_FUNC_H
|
||||
|
||||
#include "command_type.h"
|
||||
#include "network/network_type.h"
|
||||
#include "company_type.h"
|
||||
#include "company_func.h"
|
||||
#include "core/backup_type.hpp"
|
||||
#include "command_type.h"
|
||||
#include "company_func.h"
|
||||
#include "company_type.h"
|
||||
#include "misc/endian_buffer.hpp"
|
||||
#include "network/network_type.h"
|
||||
#include "tile_map.h"
|
||||
|
||||
/**
|
||||
|
@ -56,11 +56,22 @@ static constexpr inline DoCommandFlags CommandFlagsToDCFlags(CommandFlags cmd_fl
|
|||
|
||||
/** Helper class to keep track of command nesting level. */
|
||||
struct RecursiveCommandCounter {
|
||||
RecursiveCommandCounter() noexcept { _counter++; }
|
||||
~RecursiveCommandCounter() noexcept { _counter--; }
|
||||
RecursiveCommandCounter() noexcept
|
||||
{
|
||||
_counter++;
|
||||
}
|
||||
|
||||
~RecursiveCommandCounter() noexcept
|
||||
{
|
||||
_counter--;
|
||||
}
|
||||
|
||||
/** Are we in the top-level command execution? */
|
||||
bool IsTopLevel() const { return _counter == 1; }
|
||||
bool IsTopLevel() const
|
||||
{
|
||||
return _counter == 1;
|
||||
}
|
||||
|
||||
private:
|
||||
static int _counter;
|
||||
};
|
||||
|
@ -80,7 +91,8 @@ private:
|
|||
# define SILENCE_GCC_FUNCTION_POINTER_CAST
|
||||
#endif
|
||||
|
||||
template <Commands TCmd, typename T, bool THasTile> struct CommandHelper;
|
||||
template <Commands TCmd, typename T, bool THasTile>
|
||||
struct CommandHelper;
|
||||
|
||||
class CommandHelperBase {
|
||||
protected:
|
||||
|
@ -90,7 +102,8 @@ protected:
|
|||
static void InternalPostResult(CommandCost &res, TileIndex tile, bool estimate_only, bool only_sending, StringID err_message, bool my_cmd);
|
||||
static bool InternalExecutePrepTest(CommandFlags cmd_flags, TileIndex tile, Backup<CompanyID> &cur_company);
|
||||
static std::tuple<bool, bool, bool> InternalExecuteValidateTestAndPrepExec(CommandCost &res, CommandFlags cmd_flags, bool estimate_only, bool network_command, Backup<CompanyID> &cur_company);
|
||||
static CommandCost InternalExecuteProcessResult(Commands cmd, CommandFlags cmd_flags, const CommandCost &res_test, const CommandCost &res_exec, Money extra_cash, TileIndex tile, Backup<CompanyID> &cur_company);
|
||||
static CommandCost InternalExecuteProcessResult(
|
||||
Commands cmd, CommandFlags cmd_flags, const CommandCost &res_test, const CommandCost &res_exec, Money extra_cash, TileIndex tile, Backup<CompanyID> &cur_company);
|
||||
static void LogCommandExecution(Commands cmd, StringID err_message, const CommandDataBuffer &args, bool failed);
|
||||
};
|
||||
|
||||
|
@ -102,7 +115,7 @@ protected:
|
|||
* @tparam Targs The command parameter types.
|
||||
*/
|
||||
template <Commands Tcmd, typename Tret, typename... Targs>
|
||||
struct CommandHelper<Tcmd, Tret(*)(DoCommandFlags, Targs...), true> : protected CommandHelperBase {
|
||||
struct CommandHelper<Tcmd, Tret (*)(DoCommandFlags, Targs...), true> : protected CommandHelperBase {
|
||||
private:
|
||||
/** Extract the \c CommandCost from a command proc result. */
|
||||
static inline CommandCost &ExtractCommandCost(Tret &ret)
|
||||
|
@ -169,19 +182,30 @@ public:
|
|||
* @param err_message Message prefix to show on error
|
||||
* @param args Parameters for the command
|
||||
*/
|
||||
static inline bool Post(StringID err_message, Targs... args) { return Post<CommandCallback>(err_message, nullptr, std::forward<Targs>(args)...); }
|
||||
static inline bool Post(StringID err_message, Targs... args)
|
||||
{
|
||||
return Post<CommandCallback>(err_message, nullptr, std::forward<Targs>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for the long Post when not using an error message.
|
||||
* @param callback A callback function to call after the command is finished
|
||||
* @param args Parameters for the command
|
||||
*/
|
||||
template <typename Tcallback>
|
||||
static inline bool Post(Tcallback *callback, Targs... args) { return Post((StringID)0, callback, std::forward<Targs>(args)...); }
|
||||
static inline bool Post(Tcallback *callback, Targs... args)
|
||||
{
|
||||
return Post((StringID)0, callback, std::forward<Targs>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for the long Post when not using a callback or an error message.
|
||||
* @param args Parameters for the command
|
||||
*/
|
||||
static inline bool Post(Targs... args) { return Post<CommandCallback>((StringID)0, nullptr, std::forward<Targs>(args)...); }
|
||||
static inline bool Post(Targs... args)
|
||||
{
|
||||
return Post<CommandCallback>((StringID)0, nullptr, std::forward<Targs>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Top-level network safe command execution for the current company.
|
||||
|
@ -240,7 +264,7 @@ public:
|
|||
template <typename Tcallback>
|
||||
static Tret Unsafe(StringID err_message, Tcallback *callback, bool my_cmd, bool estimate_only, TileIndex location, std::tuple<Targs...> args)
|
||||
{
|
||||
return Execute(err_message, reinterpret_cast<CommandCallback *>(reinterpret_cast<void(*)()>(callback)), my_cmd, estimate_only, false, location, std::move(args));
|
||||
return Execute(err_message, reinterpret_cast<CommandCallback *>(reinterpret_cast<void (*)()>(callback)), my_cmd, estimate_only, false, location, std::move(args));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -264,7 +288,11 @@ protected:
|
|||
template <template <typename...> typename Tt, typename T1, typename... Ts>
|
||||
static inline Tt<Ts...> RemoveFirstTupleElement(const Tt<T1, Ts...> &tuple)
|
||||
{
|
||||
return std::apply([](auto &&, const auto&... args) { return std::tie(args...); }, tuple);
|
||||
return std::apply(
|
||||
[](auto &&, const auto &...args) {
|
||||
return std::tie(args...);
|
||||
},
|
||||
tuple);
|
||||
}
|
||||
|
||||
template <typename Tcallback>
|
||||
|
@ -291,7 +319,7 @@ protected:
|
|||
/* Only set client IDs when the command does not come from the network. */
|
||||
if (!network_command && GetCommandFlags<Tcmd>().Test(CommandFlag::ClientID)) SetClientIds(args, std::index_sequence_for<Targs...>{});
|
||||
|
||||
Tret res = Execute(err_message, reinterpret_cast<CommandCallback *>(reinterpret_cast<void(*)()>(callback)), my_cmd, estimate_only, network_command, tile, args);
|
||||
Tret res = Execute(err_message, reinterpret_cast<CommandCallback *>(reinterpret_cast<void (*)()>(callback)), my_cmd, estimate_only, network_command, tile, args);
|
||||
InternalPostResult(ExtractCommandCost(res), tile, estimate_only, only_sending, err_message, my_cmd);
|
||||
|
||||
if (!estimate_only && !only_sending && callback != nullptr) {
|
||||
|
@ -421,8 +449,7 @@ protected:
|
|||
* @tparam Targs The command parameter types.
|
||||
*/
|
||||
template <Commands Tcmd, typename Tret, typename... Targs>
|
||||
struct CommandHelper<Tcmd, Tret(*)(DoCommandFlags, Targs...), false> : CommandHelper<Tcmd, Tret(*)(DoCommandFlags, Targs...), true>
|
||||
{
|
||||
struct CommandHelper<Tcmd, Tret (*)(DoCommandFlags, Targs...), false> : CommandHelper<Tcmd, Tret (*)(DoCommandFlags, Targs...), true> {
|
||||
/* Do not allow Post without explicit location. */
|
||||
static inline bool Post(StringID err_message, Targs... args) = delete;
|
||||
template <typename Tcallback>
|
||||
|
@ -437,7 +464,11 @@ struct CommandHelper<Tcmd, Tret(*)(DoCommandFlags, Targs...), false> : CommandHe
|
|||
* @param location Tile location for user feedback.
|
||||
* @param args Parameters for the command
|
||||
*/
|
||||
static inline bool Post(StringID err_message, TileIndex location, Targs... args) { return Post<CommandCallback>(err_message, nullptr, location, std::forward<Targs>(args)...); }
|
||||
static inline bool Post(StringID err_message, TileIndex location, Targs... args)
|
||||
{
|
||||
return Post<CommandCallback>(err_message, nullptr, location, std::forward<Targs>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for Post when not using an error message.
|
||||
* @param callback A callback function to call after the command is finished
|
||||
|
@ -445,13 +476,20 @@ struct CommandHelper<Tcmd, Tret(*)(DoCommandFlags, Targs...), false> : CommandHe
|
|||
* @param args Parameters for the command
|
||||
*/
|
||||
template <typename Tcallback>
|
||||
static inline bool Post(Tcallback *callback, TileIndex location, Targs... args) { return Post((StringID)0, callback, location, std::forward<Targs>(args)...); }
|
||||
static inline bool Post(Tcallback *callback, TileIndex location, Targs... args)
|
||||
{
|
||||
return Post((StringID)0, callback, location, std::forward<Targs>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for Post when not using a callback or an error message.
|
||||
* @param location Tile location for user feedback.
|
||||
* @param args Parameters for the command*
|
||||
*/
|
||||
static inline bool Post(TileIndex location, Targs... args) { return Post<CommandCallback>((StringID)0, nullptr, location, std::forward<Targs>(args)...); }
|
||||
static inline bool Post(TileIndex location, Targs... args)
|
||||
{
|
||||
return Post<CommandCallback>((StringID)0, nullptr, location, std::forward<Targs>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post variant that takes a TileIndex (for error window location and text effects) for
|
||||
|
@ -464,7 +502,7 @@ struct CommandHelper<Tcmd, Tret(*)(DoCommandFlags, Targs...), false> : CommandHe
|
|||
template <typename Tcallback>
|
||||
static inline bool Post(StringID err_message, Tcallback *callback, TileIndex location, Targs... args)
|
||||
{
|
||||
return CommandHelper<Tcmd, Tret(*)(DoCommandFlags, Targs...), true>::InternalPost(err_message, callback, true, false, location, std::forward_as_tuple(args...));
|
||||
return CommandHelper<Tcmd, Tret (*)(DoCommandFlags, Targs...), true>::InternalPost(err_message, callback, true, false, location, std::forward_as_tuple(args...));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -22,10 +22,10 @@ struct GRFFile;
|
|||
* a possible error message/state together.
|
||||
*/
|
||||
class CommandCost {
|
||||
Money cost; ///< The cost of this action
|
||||
StringID message; ///< Warning message for when success is unset
|
||||
ExpensesType expense_type; ///< the type of expence as shown on the finances view
|
||||
bool success; ///< Whether the command went fine up to this moment
|
||||
Money cost; ///< The cost of this action
|
||||
StringID message; ///< Warning message for when success is unset
|
||||
ExpensesType expense_type; ///< the type of expence as shown on the finances view
|
||||
bool success; ///< Whether the command went fine up to this moment
|
||||
Owner owner = CompanyID::Invalid(); ///< Originator owner of error.
|
||||
StringID extra_message = INVALID_STRING_ID; ///< Additional warning message for when success is unset
|
||||
EncodedString encoded_message{}; ///< Encoded error message, used if the error message includes parameters.
|
||||
|
@ -181,7 +181,11 @@ public:
|
|||
};
|
||||
|
||||
CommandCost CommandCostWithParam(StringID str, uint64_t value);
|
||||
CommandCost CommandCostWithParam(StringID str, ConvertibleThroughBase auto value) { return CommandCostWithParam(str, value.base()); }
|
||||
|
||||
CommandCost CommandCostWithParam(StringID str, ConvertibleThroughBase auto value)
|
||||
{
|
||||
return CommandCostWithParam(str, value.base());
|
||||
}
|
||||
|
||||
/**
|
||||
* List of commands.
|
||||
|
@ -194,185 +198,185 @@ CommandCost CommandCostWithParam(StringID str, ConvertibleThroughBase auto value
|
|||
* @see _command_proc_table
|
||||
*/
|
||||
enum Commands : uint8_t {
|
||||
CMD_BUILD_RAILROAD_TRACK, ///< build a rail track
|
||||
CMD_REMOVE_RAILROAD_TRACK, ///< remove a rail track
|
||||
CMD_BUILD_SINGLE_RAIL, ///< build a single rail track
|
||||
CMD_REMOVE_SINGLE_RAIL, ///< remove a single rail track
|
||||
CMD_LANDSCAPE_CLEAR, ///< demolish a tile
|
||||
CMD_BUILD_BRIDGE, ///< build a bridge
|
||||
CMD_BUILD_RAIL_STATION, ///< build a rail station
|
||||
CMD_BUILD_TRAIN_DEPOT, ///< build a train depot
|
||||
CMD_BUILD_SINGLE_SIGNAL, ///< build a signal
|
||||
CMD_REMOVE_SINGLE_SIGNAL, ///< remove a signal
|
||||
CMD_TERRAFORM_LAND, ///< terraform a tile
|
||||
CMD_BUILD_OBJECT, ///< build an object
|
||||
CMD_BUILD_OBJECT_AREA, ///< build an area of objects
|
||||
CMD_BUILD_TUNNEL, ///< build a tunnel
|
||||
CMD_BUILD_RAILROAD_TRACK, ///< build a rail track
|
||||
CMD_REMOVE_RAILROAD_TRACK, ///< remove a rail track
|
||||
CMD_BUILD_SINGLE_RAIL, ///< build a single rail track
|
||||
CMD_REMOVE_SINGLE_RAIL, ///< remove a single rail track
|
||||
CMD_LANDSCAPE_CLEAR, ///< demolish a tile
|
||||
CMD_BUILD_BRIDGE, ///< build a bridge
|
||||
CMD_BUILD_RAIL_STATION, ///< build a rail station
|
||||
CMD_BUILD_TRAIN_DEPOT, ///< build a train depot
|
||||
CMD_BUILD_SINGLE_SIGNAL, ///< build a signal
|
||||
CMD_REMOVE_SINGLE_SIGNAL, ///< remove a signal
|
||||
CMD_TERRAFORM_LAND, ///< terraform a tile
|
||||
CMD_BUILD_OBJECT, ///< build an object
|
||||
CMD_BUILD_OBJECT_AREA, ///< build an area of objects
|
||||
CMD_BUILD_TUNNEL, ///< build a tunnel
|
||||
|
||||
CMD_REMOVE_FROM_RAIL_STATION, ///< remove a (rectangle of) tiles from a rail station
|
||||
CMD_CONVERT_RAIL, ///< convert a rail type
|
||||
CMD_REMOVE_FROM_RAIL_STATION, ///< remove a (rectangle of) tiles from a rail station
|
||||
CMD_CONVERT_RAIL, ///< convert a rail type
|
||||
|
||||
CMD_BUILD_RAIL_WAYPOINT, ///< build a waypoint
|
||||
CMD_RENAME_WAYPOINT, ///< rename a waypoint
|
||||
CMD_REMOVE_FROM_RAIL_WAYPOINT, ///< remove a (rectangle of) tiles from a rail waypoint
|
||||
CMD_BUILD_RAIL_WAYPOINT, ///< build a waypoint
|
||||
CMD_RENAME_WAYPOINT, ///< rename a waypoint
|
||||
CMD_REMOVE_FROM_RAIL_WAYPOINT, ///< remove a (rectangle of) tiles from a rail waypoint
|
||||
|
||||
CMD_BUILD_ROAD_WAYPOINT, ///< build a road waypoint
|
||||
CMD_REMOVE_FROM_ROAD_WAYPOINT, ///< remove a (rectangle of) tiles from a road waypoint
|
||||
CMD_BUILD_ROAD_WAYPOINT, ///< build a road waypoint
|
||||
CMD_REMOVE_FROM_ROAD_WAYPOINT, ///< remove a (rectangle of) tiles from a road waypoint
|
||||
|
||||
CMD_BUILD_ROAD_STOP, ///< build a road stop
|
||||
CMD_REMOVE_ROAD_STOP, ///< remove a road stop
|
||||
CMD_BUILD_LONG_ROAD, ///< build a complete road (not a "half" one)
|
||||
CMD_REMOVE_LONG_ROAD, ///< remove a complete road (not a "half" one)
|
||||
CMD_BUILD_ROAD, ///< build a "half" road
|
||||
CMD_BUILD_ROAD_DEPOT, ///< build a road depot
|
||||
CMD_CONVERT_ROAD, ///< convert a road type
|
||||
CMD_BUILD_ROAD_STOP, ///< build a road stop
|
||||
CMD_REMOVE_ROAD_STOP, ///< remove a road stop
|
||||
CMD_BUILD_LONG_ROAD, ///< build a complete road (not a "half" one)
|
||||
CMD_REMOVE_LONG_ROAD, ///< remove a complete road (not a "half" one)
|
||||
CMD_BUILD_ROAD, ///< build a "half" road
|
||||
CMD_BUILD_ROAD_DEPOT, ///< build a road depot
|
||||
CMD_CONVERT_ROAD, ///< convert a road type
|
||||
|
||||
CMD_BUILD_AIRPORT, ///< build an airport
|
||||
CMD_BUILD_AIRPORT, ///< build an airport
|
||||
|
||||
CMD_BUILD_DOCK, ///< build a dock
|
||||
CMD_BUILD_DOCK, ///< build a dock
|
||||
|
||||
CMD_BUILD_SHIP_DEPOT, ///< build a ship depot
|
||||
CMD_BUILD_BUOY, ///< build a buoy
|
||||
CMD_BUILD_SHIP_DEPOT, ///< build a ship depot
|
||||
CMD_BUILD_BUOY, ///< build a buoy
|
||||
|
||||
CMD_PLANT_TREE, ///< plant a tree
|
||||
CMD_PLANT_TREE, ///< plant a tree
|
||||
|
||||
CMD_BUILD_VEHICLE, ///< build a vehicle
|
||||
CMD_SELL_VEHICLE, ///< sell a vehicle
|
||||
CMD_REFIT_VEHICLE, ///< refit the cargo space of a vehicle
|
||||
CMD_SEND_VEHICLE_TO_DEPOT, ///< send a vehicle to a depot
|
||||
CMD_SET_VEHICLE_VISIBILITY, ///< hide or unhide a vehicle in the build vehicle and autoreplace GUIs
|
||||
CMD_BUILD_VEHICLE, ///< build a vehicle
|
||||
CMD_SELL_VEHICLE, ///< sell a vehicle
|
||||
CMD_REFIT_VEHICLE, ///< refit the cargo space of a vehicle
|
||||
CMD_SEND_VEHICLE_TO_DEPOT, ///< send a vehicle to a depot
|
||||
CMD_SET_VEHICLE_VISIBILITY, ///< hide or unhide a vehicle in the build vehicle and autoreplace GUIs
|
||||
|
||||
CMD_MOVE_RAIL_VEHICLE, ///< move a rail vehicle (in the depot)
|
||||
CMD_FORCE_TRAIN_PROCEED, ///< proceed a train to pass a red signal
|
||||
CMD_REVERSE_TRAIN_DIRECTION, ///< turn a train around
|
||||
CMD_MOVE_RAIL_VEHICLE, ///< move a rail vehicle (in the depot)
|
||||
CMD_FORCE_TRAIN_PROCEED, ///< proceed a train to pass a red signal
|
||||
CMD_REVERSE_TRAIN_DIRECTION, ///< turn a train around
|
||||
|
||||
CMD_CLEAR_ORDER_BACKUP, ///< clear the order backup of a given user/tile
|
||||
CMD_MODIFY_ORDER, ///< modify an order (like set full-load)
|
||||
CMD_SKIP_TO_ORDER, ///< skip an order to the next of specific one
|
||||
CMD_DELETE_ORDER, ///< delete an order
|
||||
CMD_INSERT_ORDER, ///< insert a new order
|
||||
CMD_CLEAR_ORDER_BACKUP, ///< clear the order backup of a given user/tile
|
||||
CMD_MODIFY_ORDER, ///< modify an order (like set full-load)
|
||||
CMD_SKIP_TO_ORDER, ///< skip an order to the next of specific one
|
||||
CMD_DELETE_ORDER, ///< delete an order
|
||||
CMD_INSERT_ORDER, ///< insert a new order
|
||||
|
||||
CMD_CHANGE_SERVICE_INT, ///< change the server interval of a vehicle
|
||||
CMD_CHANGE_SERVICE_INT, ///< change the server interval of a vehicle
|
||||
|
||||
CMD_BUILD_INDUSTRY, ///< build a new industry
|
||||
CMD_INDUSTRY_SET_FLAGS, ///< change industry control flags
|
||||
CMD_INDUSTRY_SET_EXCLUSIVITY, ///< change industry exclusive consumer/supplier
|
||||
CMD_INDUSTRY_SET_TEXT, ///< change additional text for the industry
|
||||
CMD_INDUSTRY_SET_PRODUCTION, ///< change industry production
|
||||
CMD_BUILD_INDUSTRY, ///< build a new industry
|
||||
CMD_INDUSTRY_SET_FLAGS, ///< change industry control flags
|
||||
CMD_INDUSTRY_SET_EXCLUSIVITY, ///< change industry exclusive consumer/supplier
|
||||
CMD_INDUSTRY_SET_TEXT, ///< change additional text for the industry
|
||||
CMD_INDUSTRY_SET_PRODUCTION, ///< change industry production
|
||||
|
||||
CMD_SET_COMPANY_MANAGER_FACE, ///< set the manager's face of the company
|
||||
CMD_SET_COMPANY_COLOUR, ///< set the colour of the company
|
||||
CMD_SET_COMPANY_MANAGER_FACE, ///< set the manager's face of the company
|
||||
CMD_SET_COMPANY_COLOUR, ///< set the colour of the company
|
||||
|
||||
CMD_INCREASE_LOAN, ///< increase the loan from the bank
|
||||
CMD_DECREASE_LOAN, ///< decrease the loan from the bank
|
||||
CMD_SET_COMPANY_MAX_LOAN, ///< sets the max loan for the company
|
||||
CMD_INCREASE_LOAN, ///< increase the loan from the bank
|
||||
CMD_DECREASE_LOAN, ///< decrease the loan from the bank
|
||||
CMD_SET_COMPANY_MAX_LOAN, ///< sets the max loan for the company
|
||||
|
||||
CMD_WANT_ENGINE_PREVIEW, ///< confirm the preview of an engine
|
||||
CMD_ENGINE_CTRL, ///< control availability of the engine for companies
|
||||
CMD_WANT_ENGINE_PREVIEW, ///< confirm the preview of an engine
|
||||
CMD_ENGINE_CTRL, ///< control availability of the engine for companies
|
||||
|
||||
CMD_RENAME_VEHICLE, ///< rename a whole vehicle
|
||||
CMD_RENAME_ENGINE, ///< rename a engine (in the engine list)
|
||||
CMD_RENAME_COMPANY, ///< change the company name
|
||||
CMD_RENAME_PRESIDENT, ///< change the president name
|
||||
CMD_RENAME_STATION, ///< rename a station
|
||||
CMD_RENAME_DEPOT, ///< rename a depot
|
||||
CMD_RENAME_VEHICLE, ///< rename a whole vehicle
|
||||
CMD_RENAME_ENGINE, ///< rename a engine (in the engine list)
|
||||
CMD_RENAME_COMPANY, ///< change the company name
|
||||
CMD_RENAME_PRESIDENT, ///< change the president name
|
||||
CMD_RENAME_STATION, ///< rename a station
|
||||
CMD_RENAME_DEPOT, ///< rename a depot
|
||||
|
||||
CMD_PLACE_SIGN, ///< place a sign
|
||||
CMD_RENAME_SIGN, ///< rename a sign
|
||||
CMD_PLACE_SIGN, ///< place a sign
|
||||
CMD_RENAME_SIGN, ///< rename a sign
|
||||
|
||||
CMD_TURN_ROADVEH, ///< turn a road vehicle around
|
||||
CMD_TURN_ROADVEH, ///< turn a road vehicle around
|
||||
|
||||
CMD_PAUSE, ///< pause the game
|
||||
CMD_PAUSE, ///< pause the game
|
||||
|
||||
CMD_BUY_COMPANY, ///< buy a company which is bankrupt
|
||||
CMD_BUY_COMPANY, ///< buy a company which is bankrupt
|
||||
|
||||
CMD_FOUND_TOWN, ///< found a town
|
||||
CMD_RENAME_TOWN, ///< rename a town
|
||||
CMD_DO_TOWN_ACTION, ///< do a action from the town detail window (like advertises or bribe)
|
||||
CMD_TOWN_CARGO_GOAL, ///< set the goal of a cargo for a town
|
||||
CMD_TOWN_GROWTH_RATE, ///< set the town growth rate
|
||||
CMD_TOWN_RATING, ///< set rating of a company in a town
|
||||
CMD_TOWN_SET_TEXT, ///< set the custom text of a town
|
||||
CMD_EXPAND_TOWN, ///< expand a town
|
||||
CMD_DELETE_TOWN, ///< delete a town
|
||||
CMD_PLACE_HOUSE, ///< place a house
|
||||
CMD_FOUND_TOWN, ///< found a town
|
||||
CMD_RENAME_TOWN, ///< rename a town
|
||||
CMD_DO_TOWN_ACTION, ///< do a action from the town detail window (like advertises or bribe)
|
||||
CMD_TOWN_CARGO_GOAL, ///< set the goal of a cargo for a town
|
||||
CMD_TOWN_GROWTH_RATE, ///< set the town growth rate
|
||||
CMD_TOWN_RATING, ///< set rating of a company in a town
|
||||
CMD_TOWN_SET_TEXT, ///< set the custom text of a town
|
||||
CMD_EXPAND_TOWN, ///< expand a town
|
||||
CMD_DELETE_TOWN, ///< delete a town
|
||||
CMD_PLACE_HOUSE, ///< place a house
|
||||
|
||||
CMD_ORDER_REFIT, ///< change the refit information of an order (for "goto depot" )
|
||||
CMD_CLONE_ORDER, ///< clone (and share) an order
|
||||
CMD_CLEAR_AREA, ///< clear an area
|
||||
CMD_ORDER_REFIT, ///< change the refit information of an order (for "goto depot" )
|
||||
CMD_CLONE_ORDER, ///< clone (and share) an order
|
||||
CMD_CLEAR_AREA, ///< clear an area
|
||||
|
||||
CMD_MONEY_CHEAT, ///< do the money cheat
|
||||
CMD_CHANGE_BANK_BALANCE, ///< change bank balance to charge costs or give money from a GS
|
||||
CMD_BUILD_CANAL, ///< build a canal
|
||||
CMD_MONEY_CHEAT, ///< do the money cheat
|
||||
CMD_CHANGE_BANK_BALANCE, ///< change bank balance to charge costs or give money from a GS
|
||||
CMD_BUILD_CANAL, ///< build a canal
|
||||
|
||||
CMD_CREATE_SUBSIDY, ///< create a new subsidy
|
||||
CMD_COMPANY_CTRL, ///< used in multiplayer to create a new companies etc.
|
||||
CMD_CREATE_SUBSIDY, ///< create a new subsidy
|
||||
CMD_COMPANY_CTRL, ///< used in multiplayer to create a new companies etc.
|
||||
CMD_COMPANY_ALLOW_LIST_CTRL, ///< Used in multiplayer to add/remove a client's public key to/from the company's allow list.
|
||||
CMD_CUSTOM_NEWS_ITEM, ///< create a custom news message
|
||||
CMD_CREATE_GOAL, ///< create a new goal
|
||||
CMD_REMOVE_GOAL, ///< remove a goal
|
||||
CMD_SET_GOAL_DESTINATION, ///< update goal destination of a goal
|
||||
CMD_SET_GOAL_TEXT, ///< update goal text of a goal
|
||||
CMD_SET_GOAL_PROGRESS, ///< update goal progress text of a goal
|
||||
CMD_SET_GOAL_COMPLETED, ///< update goal completed status of a goal
|
||||
CMD_GOAL_QUESTION, ///< ask a goal related question
|
||||
CMD_GOAL_QUESTION_ANSWER, ///< answer(s) to CMD_GOAL_QUESTION
|
||||
CMD_CREATE_STORY_PAGE, ///< create a new story page
|
||||
CMD_CREATE_STORY_PAGE_ELEMENT, ///< create a new story page element
|
||||
CMD_UPDATE_STORY_PAGE_ELEMENT, ///< update a story page element
|
||||
CMD_SET_STORY_PAGE_TITLE, ///< update title of a story page
|
||||
CMD_SET_STORY_PAGE_DATE, ///< update date of a story page
|
||||
CMD_SHOW_STORY_PAGE, ///< show a story page
|
||||
CMD_REMOVE_STORY_PAGE, ///< remove a story page
|
||||
CMD_REMOVE_STORY_PAGE_ELEMENT, ///< remove a story page element
|
||||
CMD_SCROLL_VIEWPORT, ///< scroll main viewport of players
|
||||
CMD_STORY_PAGE_BUTTON, ///< selection via story page button
|
||||
CMD_CUSTOM_NEWS_ITEM, ///< create a custom news message
|
||||
CMD_CREATE_GOAL, ///< create a new goal
|
||||
CMD_REMOVE_GOAL, ///< remove a goal
|
||||
CMD_SET_GOAL_DESTINATION, ///< update goal destination of a goal
|
||||
CMD_SET_GOAL_TEXT, ///< update goal text of a goal
|
||||
CMD_SET_GOAL_PROGRESS, ///< update goal progress text of a goal
|
||||
CMD_SET_GOAL_COMPLETED, ///< update goal completed status of a goal
|
||||
CMD_GOAL_QUESTION, ///< ask a goal related question
|
||||
CMD_GOAL_QUESTION_ANSWER, ///< answer(s) to CMD_GOAL_QUESTION
|
||||
CMD_CREATE_STORY_PAGE, ///< create a new story page
|
||||
CMD_CREATE_STORY_PAGE_ELEMENT, ///< create a new story page element
|
||||
CMD_UPDATE_STORY_PAGE_ELEMENT, ///< update a story page element
|
||||
CMD_SET_STORY_PAGE_TITLE, ///< update title of a story page
|
||||
CMD_SET_STORY_PAGE_DATE, ///< update date of a story page
|
||||
CMD_SHOW_STORY_PAGE, ///< show a story page
|
||||
CMD_REMOVE_STORY_PAGE, ///< remove a story page
|
||||
CMD_REMOVE_STORY_PAGE_ELEMENT, ///< remove a story page element
|
||||
CMD_SCROLL_VIEWPORT, ///< scroll main viewport of players
|
||||
CMD_STORY_PAGE_BUTTON, ///< selection via story page button
|
||||
|
||||
CMD_LEVEL_LAND, ///< level land
|
||||
CMD_LEVEL_LAND, ///< level land
|
||||
|
||||
CMD_BUILD_LOCK, ///< build a lock
|
||||
CMD_BUILD_LOCK, ///< build a lock
|
||||
|
||||
CMD_BUILD_SIGNAL_TRACK, ///< add signals along a track (by dragging)
|
||||
CMD_REMOVE_SIGNAL_TRACK, ///< remove signals along a track (by dragging)
|
||||
CMD_BUILD_SIGNAL_TRACK, ///< add signals along a track (by dragging)
|
||||
CMD_REMOVE_SIGNAL_TRACK, ///< remove signals along a track (by dragging)
|
||||
|
||||
CMD_GIVE_MONEY, ///< give money to another company
|
||||
CMD_CHANGE_SETTING, ///< change a setting
|
||||
CMD_CHANGE_COMPANY_SETTING, ///< change a company setting
|
||||
CMD_GIVE_MONEY, ///< give money to another company
|
||||
CMD_CHANGE_SETTING, ///< change a setting
|
||||
CMD_CHANGE_COMPANY_SETTING, ///< change a company setting
|
||||
|
||||
CMD_SET_AUTOREPLACE, ///< set an autoreplace entry
|
||||
CMD_SET_AUTOREPLACE, ///< set an autoreplace entry
|
||||
|
||||
CMD_CLONE_VEHICLE, ///< clone a vehicle
|
||||
CMD_START_STOP_VEHICLE, ///< start or stop a vehicle
|
||||
CMD_MASS_START_STOP, ///< start/stop all vehicles (in a depot)
|
||||
CMD_AUTOREPLACE_VEHICLE, ///< replace/renew a vehicle while it is in a depot
|
||||
CMD_DEPOT_SELL_ALL_VEHICLES, ///< sell all vehicles which are in a given depot
|
||||
CMD_DEPOT_MASS_AUTOREPLACE, ///< force the autoreplace to take action in a given depot
|
||||
CMD_CLONE_VEHICLE, ///< clone a vehicle
|
||||
CMD_START_STOP_VEHICLE, ///< start or stop a vehicle
|
||||
CMD_MASS_START_STOP, ///< start/stop all vehicles (in a depot)
|
||||
CMD_AUTOREPLACE_VEHICLE, ///< replace/renew a vehicle while it is in a depot
|
||||
CMD_DEPOT_SELL_ALL_VEHICLES, ///< sell all vehicles which are in a given depot
|
||||
CMD_DEPOT_MASS_AUTOREPLACE, ///< force the autoreplace to take action in a given depot
|
||||
|
||||
CMD_CREATE_GROUP, ///< create a new group
|
||||
CMD_DELETE_GROUP, ///< delete a group
|
||||
CMD_ALTER_GROUP, ///< alter a group
|
||||
CMD_ADD_VEHICLE_GROUP, ///< add a vehicle to a group
|
||||
CMD_ADD_SHARED_VEHICLE_GROUP, ///< add all other shared vehicles to a group which are missing
|
||||
CMD_REMOVE_ALL_VEHICLES_GROUP, ///< remove all vehicles from a group
|
||||
CMD_SET_GROUP_FLAG, ///< set/clear a flag for a group
|
||||
CMD_SET_GROUP_LIVERY, ///< set the livery for a group
|
||||
CMD_CREATE_GROUP, ///< create a new group
|
||||
CMD_DELETE_GROUP, ///< delete a group
|
||||
CMD_ALTER_GROUP, ///< alter a group
|
||||
CMD_ADD_VEHICLE_GROUP, ///< add a vehicle to a group
|
||||
CMD_ADD_SHARED_VEHICLE_GROUP, ///< add all other shared vehicles to a group which are missing
|
||||
CMD_REMOVE_ALL_VEHICLES_GROUP, ///< remove all vehicles from a group
|
||||
CMD_SET_GROUP_FLAG, ///< set/clear a flag for a group
|
||||
CMD_SET_GROUP_LIVERY, ///< set the livery for a group
|
||||
|
||||
CMD_MOVE_ORDER, ///< move an order
|
||||
CMD_CHANGE_TIMETABLE, ///< change the timetable for a vehicle
|
||||
CMD_BULK_CHANGE_TIMETABLE, ///< change the timetable for all orders of a vehicle
|
||||
CMD_SET_VEHICLE_ON_TIME, ///< set the vehicle on time feature (timetable)
|
||||
CMD_AUTOFILL_TIMETABLE, ///< autofill the timetable
|
||||
CMD_SET_TIMETABLE_START, ///< set the date that a timetable should start
|
||||
CMD_MOVE_ORDER, ///< move an order
|
||||
CMD_CHANGE_TIMETABLE, ///< change the timetable for a vehicle
|
||||
CMD_BULK_CHANGE_TIMETABLE, ///< change the timetable for all orders of a vehicle
|
||||
CMD_SET_VEHICLE_ON_TIME, ///< set the vehicle on time feature (timetable)
|
||||
CMD_AUTOFILL_TIMETABLE, ///< autofill the timetable
|
||||
CMD_SET_TIMETABLE_START, ///< set the date that a timetable should start
|
||||
|
||||
CMD_OPEN_CLOSE_AIRPORT, ///< open/close an airport to incoming aircraft
|
||||
CMD_OPEN_CLOSE_AIRPORT, ///< open/close an airport to incoming aircraft
|
||||
|
||||
CMD_CREATE_LEAGUE_TABLE, ///< create a new league table
|
||||
CMD_CREATE_LEAGUE_TABLE_ELEMENT, ///< create a new element in a league table
|
||||
CMD_UPDATE_LEAGUE_TABLE_ELEMENT_DATA, ///< update the data fields of a league table element
|
||||
CMD_CREATE_LEAGUE_TABLE, ///< create a new league table
|
||||
CMD_CREATE_LEAGUE_TABLE_ELEMENT, ///< create a new element in a league table
|
||||
CMD_UPDATE_LEAGUE_TABLE_ELEMENT_DATA, ///< update the data fields of a league table element
|
||||
CMD_UPDATE_LEAGUE_TABLE_ELEMENT_SCORE, ///< update the score of a league table element
|
||||
CMD_REMOVE_LEAGUE_TABLE_ELEMENT, ///< remove a league table element
|
||||
CMD_REMOVE_LEAGUE_TABLE_ELEMENT, ///< remove a league table element
|
||||
|
||||
CMD_END, ///< Must ALWAYS be on the end of this list!! (period)
|
||||
CMD_END, ///< Must ALWAYS be on the end of this list!! (period)
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -393,6 +397,7 @@ enum DoCommandFlag : uint8_t {
|
|||
NoModifyTownRating, ///< do not change town rating
|
||||
ForceClearTile, ///< do not only remove the object on the tile, but also clear any water left on it
|
||||
};
|
||||
|
||||
using DoCommandFlags = EnumBitSet<DoCommandFlag, uint16_t>;
|
||||
|
||||
/**
|
||||
|
@ -419,45 +424,48 @@ using CommandFlags = EnumBitSet<CommandFlag, uint16_t>;
|
|||
/** Types of commands we have. */
|
||||
enum CommandType : uint8_t {
|
||||
CMDT_LANDSCAPE_CONSTRUCTION, ///< Construction and destruction of objects on the map.
|
||||
CMDT_VEHICLE_CONSTRUCTION, ///< Construction, modification (incl. refit) and destruction of vehicles.
|
||||
CMDT_MONEY_MANAGEMENT, ///< Management of money, i.e. loans.
|
||||
CMDT_VEHICLE_MANAGEMENT, ///< Stopping, starting, sending to depot, turning around, replace orders etc.
|
||||
CMDT_ROUTE_MANAGEMENT, ///< Modifications to route management (orders, groups, etc).
|
||||
CMDT_OTHER_MANAGEMENT, ///< Renaming stuff, changing company colours, placing signs, etc.
|
||||
CMDT_COMPANY_SETTING, ///< Changing settings related to a company.
|
||||
CMDT_SERVER_SETTING, ///< Pausing/removing companies/server settings.
|
||||
CMDT_CHEAT, ///< A cheat of some sorts.
|
||||
CMDT_VEHICLE_CONSTRUCTION, ///< Construction, modification (incl. refit) and destruction of vehicles.
|
||||
CMDT_MONEY_MANAGEMENT, ///< Management of money, i.e. loans.
|
||||
CMDT_VEHICLE_MANAGEMENT, ///< Stopping, starting, sending to depot, turning around, replace orders etc.
|
||||
CMDT_ROUTE_MANAGEMENT, ///< Modifications to route management (orders, groups, etc).
|
||||
CMDT_OTHER_MANAGEMENT, ///< Renaming stuff, changing company colours, placing signs, etc.
|
||||
CMDT_COMPANY_SETTING, ///< Changing settings related to a company.
|
||||
CMDT_SERVER_SETTING, ///< Pausing/removing companies/server settings.
|
||||
CMDT_CHEAT, ///< A cheat of some sorts.
|
||||
|
||||
CMDT_END, ///< Magic end marker.
|
||||
CMDT_END, ///< Magic end marker.
|
||||
};
|
||||
|
||||
/** Different command pause levels. */
|
||||
enum CommandPauseLevel : uint8_t {
|
||||
CMDPL_NO_ACTIONS, ///< No user actions may be executed.
|
||||
CMDPL_NO_ACTIONS, ///< No user actions may be executed.
|
||||
CMDPL_NO_CONSTRUCTION, ///< No construction actions may be executed.
|
||||
CMDPL_NO_LANDSCAPING, ///< No landscaping actions may be executed.
|
||||
CMDPL_ALL_ACTIONS, ///< All actions may be executed.
|
||||
CMDPL_NO_LANDSCAPING, ///< No landscaping actions may be executed.
|
||||
CMDPL_ALL_ACTIONS, ///< All actions may be executed.
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct CommandFunctionTraitHelper;
|
||||
|
||||
template <typename T> struct CommandFunctionTraitHelper;
|
||||
template <typename... Targs>
|
||||
struct CommandFunctionTraitHelper<CommandCost(*)(DoCommandFlags, Targs...)> {
|
||||
struct CommandFunctionTraitHelper<CommandCost (*)(DoCommandFlags, Targs...)> {
|
||||
using Args = std::tuple<std::decay_t<Targs>...>;
|
||||
using RetTypes = void;
|
||||
using CbArgs = Args;
|
||||
using CbProcType = void(*)(Commands, const CommandCost &);
|
||||
using CbProcType = void (*)(Commands, const CommandCost &);
|
||||
};
|
||||
|
||||
template <template <typename...> typename Tret, typename... Tretargs, typename... Targs>
|
||||
struct CommandFunctionTraitHelper<Tret<CommandCost, Tretargs...>(*)(DoCommandFlags, Targs...)> {
|
||||
struct CommandFunctionTraitHelper<Tret<CommandCost, Tretargs...> (*)(DoCommandFlags, Targs...)> {
|
||||
using Args = std::tuple<std::decay_t<Targs>...>;
|
||||
using RetTypes = std::tuple<std::decay_t<Tretargs>...>;
|
||||
using CbArgs = std::tuple<std::decay_t<Tretargs>..., std::decay_t<Targs>...>;
|
||||
using CbProcType = void(*)(Commands, const CommandCost &, Tretargs...);
|
||||
using CbProcType = void (*)(Commands, const CommandCost &, Tretargs...);
|
||||
};
|
||||
|
||||
/** Defines the traits of a command. */
|
||||
template <Commands Tcmd> struct CommandTraits;
|
||||
template <Commands Tcmd>
|
||||
struct CommandTraits;
|
||||
|
||||
#define DEF_CMD_TRAIT(cmd_, proc_, flags_, type_) \
|
||||
template <> struct CommandTraits<cmd_> { \
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
#ifndef COMPANY_BASE_H
|
||||
#define COMPANY_BASE_H
|
||||
|
||||
#include "road_type.h"
|
||||
#include "livery.h"
|
||||
#include "autoreplace_type.h"
|
||||
#include "group.h"
|
||||
#include "livery.h"
|
||||
#include "road_type.h"
|
||||
#include "settings_type.h"
|
||||
#include "tile_type.h"
|
||||
#include "timer/timer_game_economy.h"
|
||||
#include "settings_type.h"
|
||||
#include "group.h"
|
||||
|
||||
static const Money COMPANY_MAX_LOAN_DEFAULT = INT64_MIN;
|
||||
|
||||
|
@ -134,7 +134,7 @@ struct Company : CompanyProperties, CompanyPool::PoolItem<&_company_pool> {
|
|||
std::unique_ptr<class AIConfig> ai_config{};
|
||||
|
||||
std::array<GroupStatistics, VEH_COMPANY_END> group_all{}; ///< NOSAVE: Statistics for the ALL_GROUP group.
|
||||
std::array<GroupStatistics, VEH_COMPANY_END> group_default{}; ///< NOSAVE: Statistics for the DEFAULT_GROUP group.
|
||||
std::array<GroupStatistics, VEH_COMPANY_END> group_default{}; ///< NOSAVE: Statistics for the DEFAULT_GROUP group.
|
||||
|
||||
CompanyInfrastructure infrastructure{}; ///< NOSAVE: Counts of company owned infrastructure.
|
||||
|
||||
|
|
|
@ -8,40 +8,41 @@
|
|||
/** @file company_cmd.cpp Handling of companies. */
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "company_cmd.h"
|
||||
|
||||
#include "core/backup_type.hpp"
|
||||
#include "core/pool_func.hpp"
|
||||
#include "ai/ai.hpp"
|
||||
#include "ai/ai_config.hpp"
|
||||
#include "ai/ai_instance.hpp"
|
||||
#include "command_func.h"
|
||||
#include "company_base.h"
|
||||
#include "company_func.h"
|
||||
#include "company_gui.h"
|
||||
#include "core/backup_type.hpp"
|
||||
#include "town.h"
|
||||
#include "news_func.h"
|
||||
#include "command_func.h"
|
||||
#include "network/network.h"
|
||||
#include "network/network_func.h"
|
||||
#include "network/network_base.h"
|
||||
#include "network/network_admin.h"
|
||||
#include "ai/ai.hpp"
|
||||
#include "ai/ai_instance.hpp"
|
||||
#include "ai/ai_config.hpp"
|
||||
#include "company_manager_face.h"
|
||||
#include "window_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "sound_func.h"
|
||||
#include "rail.h"
|
||||
#include "core/pool_func.hpp"
|
||||
#include "settings_func.h"
|
||||
#include "vehicle_base.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "smallmap_gui.h"
|
||||
#include "game/game.hpp"
|
||||
#include "goal_base.h"
|
||||
#include "network/network.h"
|
||||
#include "network/network_admin.h"
|
||||
#include "network/network_base.h"
|
||||
#include "network/network_func.h"
|
||||
#include "news_func.h"
|
||||
#include "rail.h"
|
||||
#include "settings_func.h"
|
||||
#include "smallmap_gui.h"
|
||||
#include "sound_func.h"
|
||||
#include "story_base.h"
|
||||
#include "company_cmd.h"
|
||||
#include "strings_func.h"
|
||||
#include "timer/timer.h"
|
||||
#include "timer/timer_game_economy.h"
|
||||
#include "timer/timer_game_tick.h"
|
||||
#include "town.h"
|
||||
#include "vehicle_base.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "window_func.h"
|
||||
|
||||
#include "widgets/statusbar_widget.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
@ -49,11 +50,11 @@
|
|||
void ClearEnginesHiddenFlagOfCompany(CompanyID cid);
|
||||
void UpdateObjectColours(const Company *c);
|
||||
|
||||
CompanyID _local_company; ///< Company controlled by the human player at this client. Can also be #COMPANY_SPECTATOR.
|
||||
CompanyID _local_company; ///< Company controlled by the human player at this client. Can also be #COMPANY_SPECTATOR.
|
||||
CompanyID _current_company; ///< Company currently doing an action.
|
||||
ReferenceThroughBaseContainer<std::array<Colours, MAX_COMPANIES>> _company_colours; ///< NOSAVE: can be determined from company structs.
|
||||
CompanyManagerFace _company_manager_face; ///< for company manager face storage in openttd.cfg
|
||||
uint _cur_company_tick_index; ///< used to generate a name for one company that doesn't have a name yet per tick
|
||||
uint _cur_company_tick_index; ///< used to generate a name for one company that doesn't have a name yet per tick
|
||||
|
||||
CompanyPool _company_pool("Company"); ///< Pool of companies.
|
||||
INSTANTIATE_POOL_METHODS(Company)
|
||||
|
@ -67,9 +68,9 @@ Company::Company(StringID name_1, bool is_ai)
|
|||
{
|
||||
this->name_1 = name_1;
|
||||
this->is_ai = is_ai;
|
||||
this->terraform_limit = (uint32_t)_settings_game.construction.terraform_frame_burst << 16;
|
||||
this->clear_limit = (uint32_t)_settings_game.construction.clear_frame_burst << 16;
|
||||
this->tree_limit = (uint32_t)_settings_game.construction.tree_frame_burst << 16;
|
||||
this->terraform_limit = (uint32_t)_settings_game.construction.terraform_frame_burst << 16;
|
||||
this->clear_limit = (uint32_t)_settings_game.construction.clear_frame_burst << 16;
|
||||
this->tree_limit = (uint32_t)_settings_game.construction.tree_frame_burst << 16;
|
||||
this->build_object_limit = (uint32_t)_settings_game.construction.build_object_frame_burst << 16;
|
||||
|
||||
InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, CompanyID::Invalid());
|
||||
|
@ -182,20 +183,29 @@ static bool IsValidCompanyManagerFace(CompanyManagerFace cmf)
|
|||
{
|
||||
if (!AreCompanyManagerFaceBitsValid(cmf, CMFV_GEN_ETHN, GE_WM)) return false;
|
||||
|
||||
GenderEthnicity ge = (GenderEthnicity)GetCompanyManagerFaceBits(cmf, CMFV_GEN_ETHN, GE_WM);
|
||||
bool has_moustache = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge) != 0;
|
||||
GenderEthnicity ge = (GenderEthnicity)GetCompanyManagerFaceBits(cmf, CMFV_GEN_ETHN, GE_WM);
|
||||
bool has_moustache = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge) != 0;
|
||||
bool has_tie_earring = !HasBit(ge, GENDER_FEMALE) || GetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge) != 0;
|
||||
bool has_glasses = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
|
||||
bool has_glasses = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
|
||||
|
||||
if (!AreCompanyManagerFaceBitsValid(cmf, CMFV_EYE_COLOUR, ge)) return false;
|
||||
for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
|
||||
switch (cmfv) {
|
||||
case CMFV_MOUSTACHE: if (!has_moustache) continue; break;
|
||||
case CMFV_MOUSTACHE:
|
||||
if (!has_moustache) continue;
|
||||
break;
|
||||
case CMFV_LIPS:
|
||||
case CMFV_NOSE: if (has_moustache) continue; break;
|
||||
case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
|
||||
case CMFV_GLASSES: if (!has_glasses) continue; break;
|
||||
default: break;
|
||||
case CMFV_NOSE:
|
||||
if (has_moustache) continue;
|
||||
break;
|
||||
case CMFV_TIE_EARRING:
|
||||
if (!has_tie_earring) continue;
|
||||
break;
|
||||
case CMFV_GLASSES:
|
||||
if (!has_glasses) continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!AreCompanyManagerFaceBitsValid(cmf, cmfv, ge)) return false;
|
||||
}
|
||||
|
@ -276,17 +286,10 @@ static void SubtractMoneyFromAnyCompany(Company *c, const CommandCost &cost)
|
|||
c->money -= cost.GetCost();
|
||||
c->yearly_expenses[0][cost.GetExpensesType()] += cost.GetCost();
|
||||
|
||||
if (HasBit(1 << EXPENSES_TRAIN_REVENUE |
|
||||
1 << EXPENSES_ROADVEH_REVENUE |
|
||||
1 << EXPENSES_AIRCRAFT_REVENUE |
|
||||
1 << EXPENSES_SHIP_REVENUE, cost.GetExpensesType())) {
|
||||
if (HasBit(1 << EXPENSES_TRAIN_REVENUE | 1 << EXPENSES_ROADVEH_REVENUE | 1 << EXPENSES_AIRCRAFT_REVENUE | 1 << EXPENSES_SHIP_REVENUE, cost.GetExpensesType())) {
|
||||
c->cur_economy.income -= cost.GetCost();
|
||||
} else if (HasBit(1 << EXPENSES_TRAIN_RUN |
|
||||
1 << EXPENSES_ROADVEH_RUN |
|
||||
1 << EXPENSES_AIRCRAFT_RUN |
|
||||
1 << EXPENSES_SHIP_RUN |
|
||||
1 << EXPENSES_PROPERTY |
|
||||
1 << EXPENSES_LOAN_INTEREST, cost.GetExpensesType())) {
|
||||
} else if (HasBit(1 << EXPENSES_TRAIN_RUN | 1 << EXPENSES_ROADVEH_RUN | 1 << EXPENSES_AIRCRAFT_RUN | 1 << EXPENSES_SHIP_RUN | 1 << EXPENSES_PROPERTY | 1 << EXPENSES_LOAN_INTEREST,
|
||||
cost.GetExpensesType())) {
|
||||
c->cur_economy.expenses -= cost.GetCost();
|
||||
}
|
||||
|
||||
|
@ -329,9 +332,9 @@ static constexpr void UpdateLandscapingLimit(uint32_t &limit, uint64_t per_64k_f
|
|||
void UpdateLandscapingLimits()
|
||||
{
|
||||
for (Company *c : Company::Iterate()) {
|
||||
UpdateLandscapingLimit(c->terraform_limit, _settings_game.construction.terraform_per_64k_frames, _settings_game.construction.terraform_frame_burst);
|
||||
UpdateLandscapingLimit(c->clear_limit, _settings_game.construction.clear_per_64k_frames, _settings_game.construction.clear_frame_burst);
|
||||
UpdateLandscapingLimit(c->tree_limit, _settings_game.construction.tree_per_64k_frames, _settings_game.construction.tree_frame_burst);
|
||||
UpdateLandscapingLimit(c->terraform_limit, _settings_game.construction.terraform_per_64k_frames, _settings_game.construction.terraform_frame_burst);
|
||||
UpdateLandscapingLimit(c->clear_limit, _settings_game.construction.clear_per_64k_frames, _settings_game.construction.clear_frame_burst);
|
||||
UpdateLandscapingLimit(c->tree_limit, _settings_game.construction.tree_per_64k_frames, _settings_game.construction.tree_frame_burst);
|
||||
UpdateLandscapingLimit(c->build_object_limit, _settings_game.construction.build_object_per_64k_frames, _settings_game.construction.build_object_frame_burst);
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +414,7 @@ static void GenerateCompanyName(Company *c)
|
|||
str = t->townnametype - SPECSTR_TOWNNAME_START + SPECSTR_COMPANY_NAME_START;
|
||||
strp = t->townnameparts;
|
||||
|
||||
verify_name:;
|
||||
verify_name:;
|
||||
/* No companies must have this name already */
|
||||
for (const Company *cc : Company::Iterate()) {
|
||||
if (cc->name_1 == str && cc->name_2 == strp) goto bad_town_name;
|
||||
|
@ -420,7 +423,7 @@ verify_name:;
|
|||
name = GetString(str, strp);
|
||||
if (Utf8StringLength(name) >= MAX_LENGTH_COMPANY_NAME_CHARS) goto bad_town_name;
|
||||
|
||||
set_name:;
|
||||
set_name:;
|
||||
c->name_1 = str;
|
||||
c->name_2 = strp;
|
||||
|
||||
|
@ -431,8 +434,7 @@ set_name:;
|
|||
if (c->is_ai) {
|
||||
auto cni = std::make_unique<CompanyNewsInformation>(STR_NEWS_COMPANY_LAUNCH_TITLE, c);
|
||||
EncodedString headline = GetEncodedString(STR_NEWS_COMPANY_LAUNCH_DESCRIPTION, cni->company_name, t->index);
|
||||
AddNewsItem(std::move(headline),
|
||||
NewsType::CompanyInfo, NewsStyle::Company, {}, c->last_build_coordinate, {}, std::move(cni));
|
||||
AddNewsItem(std::move(headline), NewsType::CompanyInfo, NewsStyle::Company, {}, c->last_build_coordinate, {}, std::move(cni));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -454,22 +456,22 @@ bad_town_name:;
|
|||
static const uint8_t _colour_sort[COLOUR_END] = {2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 3, 1, 1, 1};
|
||||
/** Similar colours, so we can try to prevent same coloured companies. */
|
||||
static const Colours _similar_colour[COLOUR_END][2] = {
|
||||
{ COLOUR_BLUE, COLOUR_LIGHT_BLUE }, // COLOUR_DARK_BLUE
|
||||
{ COLOUR_GREEN, COLOUR_DARK_GREEN }, // COLOUR_PALE_GREEN
|
||||
{ INVALID_COLOUR, INVALID_COLOUR }, // COLOUR_PINK
|
||||
{ COLOUR_ORANGE, INVALID_COLOUR }, // COLOUR_YELLOW
|
||||
{ INVALID_COLOUR, INVALID_COLOUR }, // COLOUR_RED
|
||||
{ COLOUR_DARK_BLUE, COLOUR_BLUE }, // COLOUR_LIGHT_BLUE
|
||||
{ COLOUR_PALE_GREEN, COLOUR_DARK_GREEN }, // COLOUR_GREEN
|
||||
{ COLOUR_PALE_GREEN, COLOUR_GREEN }, // COLOUR_DARK_GREEN
|
||||
{ COLOUR_DARK_BLUE, COLOUR_LIGHT_BLUE }, // COLOUR_BLUE
|
||||
{ COLOUR_BROWN, COLOUR_ORANGE }, // COLOUR_CREAM
|
||||
{ COLOUR_PURPLE, INVALID_COLOUR }, // COLOUR_MAUVE
|
||||
{ COLOUR_MAUVE, INVALID_COLOUR }, // COLOUR_PURPLE
|
||||
{ COLOUR_YELLOW, COLOUR_CREAM }, // COLOUR_ORANGE
|
||||
{ COLOUR_CREAM, INVALID_COLOUR }, // COLOUR_BROWN
|
||||
{ COLOUR_WHITE, INVALID_COLOUR }, // COLOUR_GREY
|
||||
{ COLOUR_GREY, INVALID_COLOUR }, // COLOUR_WHITE
|
||||
{COLOUR_BLUE, COLOUR_LIGHT_BLUE}, // COLOUR_DARK_BLUE
|
||||
{COLOUR_GREEN, COLOUR_DARK_GREEN}, // COLOUR_PALE_GREEN
|
||||
{INVALID_COLOUR, INVALID_COLOUR}, // COLOUR_PINK
|
||||
{COLOUR_ORANGE, INVALID_COLOUR}, // COLOUR_YELLOW
|
||||
{INVALID_COLOUR, INVALID_COLOUR}, // COLOUR_RED
|
||||
{COLOUR_DARK_BLUE, COLOUR_BLUE}, // COLOUR_LIGHT_BLUE
|
||||
{COLOUR_PALE_GREEN, COLOUR_DARK_GREEN}, // COLOUR_GREEN
|
||||
{COLOUR_PALE_GREEN, COLOUR_GREEN}, // COLOUR_DARK_GREEN
|
||||
{COLOUR_DARK_BLUE, COLOUR_LIGHT_BLUE}, // COLOUR_BLUE
|
||||
{COLOUR_BROWN, COLOUR_ORANGE}, // COLOUR_CREAM
|
||||
{COLOUR_PURPLE, INVALID_COLOUR}, // COLOUR_MAUVE
|
||||
{COLOUR_MAUVE, INVALID_COLOUR}, // COLOUR_PURPLE
|
||||
{COLOUR_YELLOW, COLOUR_CREAM}, // COLOUR_ORANGE
|
||||
{COLOUR_CREAM, INVALID_COLOUR}, // COLOUR_BROWN
|
||||
{COLOUR_WHITE, INVALID_COLOUR}, // COLOUR_GREY
|
||||
{COLOUR_GREY, INVALID_COLOUR}, // COLOUR_WHITE
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -534,7 +536,7 @@ static Colours GenerateCompanyColour()
|
|||
static void GeneratePresidentName(Company *c)
|
||||
{
|
||||
for (;;) {
|
||||
restart:;
|
||||
restart:;
|
||||
c->president_name_2 = Random();
|
||||
c->president_name_1 = SPECSTR_PRESIDENT_NAME;
|
||||
|
||||
|
@ -561,14 +563,14 @@ restart:;
|
|||
void ResetCompanyLivery(Company *c)
|
||||
{
|
||||
for (LiveryScheme scheme = LS_BEGIN; scheme < LS_END; scheme++) {
|
||||
c->livery[scheme].in_use = 0;
|
||||
c->livery[scheme].in_use = 0;
|
||||
c->livery[scheme].colour1 = c->colour;
|
||||
c->livery[scheme].colour2 = c->colour;
|
||||
}
|
||||
|
||||
for (Group *g : Group::Iterate()) {
|
||||
if (g->owner == c->index) {
|
||||
g->livery.in_use = 0;
|
||||
g->livery.in_use = 0;
|
||||
g->livery.colour1 = c->colour;
|
||||
g->livery.colour2 = c->colour;
|
||||
}
|
||||
|
@ -638,7 +640,7 @@ Company *DoStartupNewCompany(bool is_ai, CompanyID company = CompanyID::Invalid(
|
|||
}
|
||||
|
||||
/** Start a new competitor company if possible. */
|
||||
TimeoutTimer<TimerGameTick> _new_competitor_timeout({ TimerGameTick::Priority::COMPETITOR_TIMEOUT, 0 }, []() {
|
||||
TimeoutTimer<TimerGameTick> _new_competitor_timeout({TimerGameTick::Priority::COMPETITOR_TIMEOUT, 0}, []() {
|
||||
if (_game_mode == GM_MENU || !AI::CanStartNew()) return;
|
||||
if (_networking && Company::GetNumItems() >= _settings_client.network.max_companies) return;
|
||||
if (_settings_game.difficulty.competitors_interval == 0) return;
|
||||
|
@ -682,8 +684,8 @@ bool CheckTakeoverVehicleLimit(CompanyID cbig, CompanyID csmall)
|
|||
|
||||
/* Do the combined vehicle counts stay within the limits? */
|
||||
return c1->group_all[VEH_TRAIN].num_vehicle + c2->group_all[VEH_TRAIN].num_vehicle <= _settings_game.vehicle.max_trains &&
|
||||
c1->group_all[VEH_ROAD].num_vehicle + c2->group_all[VEH_ROAD].num_vehicle <= _settings_game.vehicle.max_roadveh &&
|
||||
c1->group_all[VEH_SHIP].num_vehicle + c2->group_all[VEH_SHIP].num_vehicle <= _settings_game.vehicle.max_ships &&
|
||||
c1->group_all[VEH_ROAD].num_vehicle + c2->group_all[VEH_ROAD].num_vehicle <= _settings_game.vehicle.max_roadveh &&
|
||||
c1->group_all[VEH_SHIP].num_vehicle + c2->group_all[VEH_SHIP].num_vehicle <= _settings_game.vehicle.max_ships &&
|
||||
c1->group_all[VEH_AIRCRAFT].num_vehicle + c2->group_all[VEH_AIRCRAFT].num_vehicle <= _settings_game.vehicle.max_aircraft;
|
||||
}
|
||||
|
||||
|
@ -725,9 +727,7 @@ static void HandleBankruptcyTakeover(Company *c)
|
|||
/* Ask the company with the highest performance history first */
|
||||
for (Company *c2 : Company::Iterate()) {
|
||||
if (c2->bankrupt_asked.None() && // Don't ask companies going bankrupt themselves
|
||||
!c->bankrupt_asked.Test(c2->index) &&
|
||||
best_performance < c2->old_economy[1].performance_history &&
|
||||
CheckTakeoverVehicleLimit(c2->index, c->index)) {
|
||||
!c->bankrupt_asked.Test(c2->index) && best_performance < c2->old_economy[1].performance_history && CheckTakeoverVehicleLimit(c2->index, c->index)) {
|
||||
best_performance = c2->old_economy[1].performance_history;
|
||||
best = c2;
|
||||
}
|
||||
|
@ -781,7 +781,7 @@ void OnTick_Companies()
|
|||
/* Randomize a bit when the AI is actually going to start; ranges from 87.5% .. 112.5% of indicated value. */
|
||||
timeout += ScriptObject::GetRandomizer(OWNER_NONE).Next(timeout / 4) - timeout / 8;
|
||||
|
||||
_new_competitor_timeout.Reset({ TimerGameTick::Priority::COMPETITOR_TIMEOUT, static_cast<uint>(std::max(1, timeout)) });
|
||||
_new_competitor_timeout.Reset({TimerGameTick::Priority::COMPETITOR_TIMEOUT, static_cast<uint>(std::max(1, timeout))});
|
||||
}
|
||||
|
||||
_cur_company_tick_index = (_cur_company_tick_index + 1) % MAX_COMPANIES;
|
||||
|
@ -791,8 +791,7 @@ void OnTick_Companies()
|
|||
* A year has passed, update the economic data of all companies, and perhaps show the
|
||||
* financial overview window of the local company.
|
||||
*/
|
||||
static IntervalTimer<TimerGameEconomy> _economy_companies_yearly({TimerGameEconomy::YEAR, TimerGameEconomy::Priority::COMPANY}, [](auto)
|
||||
{
|
||||
static IntervalTimer<TimerGameEconomy> _economy_companies_yearly({TimerGameEconomy::YEAR, TimerGameEconomy::Priority::COMPANY}, [](auto) {
|
||||
/* Copy statistics */
|
||||
for (Company *c : Company::Iterate()) {
|
||||
/* Move expenses to previous years. */
|
||||
|
@ -831,7 +830,6 @@ CompanyNewsInformation::CompanyNewsInformation(StringID title, const Company *c,
|
|||
this->title = title;
|
||||
this->colour = c->colour;
|
||||
this->face = c->face;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -967,7 +965,8 @@ CommandCost CmdCompanyCtrl(DoCommandFlags flags, CompanyCtrlAction cca, CompanyI
|
|||
break;
|
||||
}
|
||||
|
||||
default: return CMD_ERROR;
|
||||
default:
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
InvalidateWindowClassesData(WC_GAME_OPTIONS);
|
||||
|
@ -1254,11 +1253,16 @@ int CompanyServiceInterval(const Company *c, VehicleType type)
|
|||
{
|
||||
const VehicleDefaultSettings *vds = (c == nullptr) ? &_settings_client.company.vehicle : &c->settings.vehicle;
|
||||
switch (type) {
|
||||
default: NOT_REACHED();
|
||||
case VEH_TRAIN: return vds->servint_trains;
|
||||
case VEH_ROAD: return vds->servint_roadveh;
|
||||
case VEH_AIRCRAFT: return vds->servint_aircraft;
|
||||
case VEH_SHIP: return vds->servint_ships;
|
||||
default:
|
||||
NOT_REACHED();
|
||||
case VEH_TRAIN:
|
||||
return vds->servint_trains;
|
||||
case VEH_ROAD:
|
||||
return vds->servint_roadveh;
|
||||
case VEH_AIRCRAFT:
|
||||
return vds->servint_aircraft;
|
||||
case VEH_SHIP:
|
||||
return vds->servint_ships;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,12 +25,12 @@ CommandCost CmdRenamePresident(DoCommandFlags flags, const std::string &text);
|
|||
CommandCost CmdSetCompanyManagerFace(DoCommandFlags flags, CompanyManagerFace cmf);
|
||||
CommandCost CmdSetCompanyColour(DoCommandFlags flags, LiveryScheme scheme, bool primary, Colours colour);
|
||||
|
||||
DEF_CMD_TRAIT(CMD_COMPANY_CTRL, CmdCompanyCtrl, CommandFlags({CommandFlag::Spectator, CommandFlag::ClientID, CommandFlag::NoEst}), CMDT_SERVER_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_COMPANY_ALLOW_LIST_CTRL, CmdCompanyAllowListCtrl, CommandFlag::NoEst, CMDT_SERVER_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_GIVE_MONEY, CmdGiveMoney, {}, CMDT_MONEY_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_RENAME_COMPANY, CmdRenameCompany, {}, CMDT_COMPANY_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_RENAME_PRESIDENT, CmdRenamePresident, {}, CMDT_COMPANY_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_SET_COMPANY_MANAGER_FACE, CmdSetCompanyManagerFace, {}, CMDT_COMPANY_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_SET_COMPANY_COLOUR, CmdSetCompanyColour, {}, CMDT_COMPANY_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_COMPANY_CTRL, CmdCompanyCtrl, CommandFlags({CommandFlag::Spectator, CommandFlag::ClientID, CommandFlag::NoEst}), CMDT_SERVER_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_COMPANY_ALLOW_LIST_CTRL, CmdCompanyAllowListCtrl, CommandFlag::NoEst, CMDT_SERVER_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_GIVE_MONEY, CmdGiveMoney, {}, CMDT_MONEY_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_RENAME_COMPANY, CmdRenameCompany, {}, CMDT_COMPANY_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_RENAME_PRESIDENT, CmdRenamePresident, {}, CMDT_COMPANY_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_SET_COMPANY_MANAGER_FACE, CmdSetCompanyManagerFace, {}, CMDT_COMPANY_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_SET_COMPANY_COLOUR, CmdSetCompanyColour, {}, CMDT_COMPANY_SETTING)
|
||||
|
||||
#endif /* COMPANY_CMD_H */
|
||||
|
|
|
@ -8,53 +8,51 @@
|
|||
/** @file company_gui.cpp %Company related GUIs. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "currency.h"
|
||||
#include "error.h"
|
||||
#include "gui.h"
|
||||
#include "window_gui.h"
|
||||
#include "textbuf_gui.h"
|
||||
#include "viewport_func.h"
|
||||
#include "company_func.h"
|
||||
#include "command_func.h"
|
||||
#include "network/network.h"
|
||||
#include "network/network_gui.h"
|
||||
#include "network/network_func.h"
|
||||
#include "newgrf.h"
|
||||
#include "company_manager_face.h"
|
||||
#include "strings_func.h"
|
||||
#include "timer/timer_game_economy.h"
|
||||
#include "dropdown_type.h"
|
||||
#include "tilehighlight_func.h"
|
||||
#include "company_base.h"
|
||||
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "command_func.h"
|
||||
#include "company_base.h"
|
||||
#include "company_cmd.h"
|
||||
#include "company_func.h"
|
||||
#include "company_manager_face.h"
|
||||
#include "currency.h"
|
||||
#include "dropdown_common_type.h"
|
||||
#include "dropdown_type.h"
|
||||
#include "economy_cmd.h"
|
||||
#include "engine_base.h"
|
||||
#include "error.h"
|
||||
#include "group_cmd.h"
|
||||
#include "group_gui.h"
|
||||
#include "gui.h"
|
||||
#include "misc_cmd.h"
|
||||
#include "network/network.h"
|
||||
#include "network/network_func.h"
|
||||
#include "network/network_gui.h"
|
||||
#include "newgrf.h"
|
||||
#include "object_cmd.h"
|
||||
#include "object_type.h"
|
||||
#include "rail.h"
|
||||
#include "road.h"
|
||||
#include "engine_base.h"
|
||||
#include "window_func.h"
|
||||
#include "road_func.h"
|
||||
#include "water.h"
|
||||
#include "station_func.h"
|
||||
#include "zoom_func.h"
|
||||
#include "sortlist_type.h"
|
||||
#include "company_cmd.h"
|
||||
#include "economy_cmd.h"
|
||||
#include "group_cmd.h"
|
||||
#include "group_gui.h"
|
||||
#include "misc_cmd.h"
|
||||
#include "object_cmd.h"
|
||||
#include "station_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "textbuf_gui.h"
|
||||
#include "tilehighlight_func.h"
|
||||
#include "timer/timer.h"
|
||||
#include "timer/timer_game_economy.h"
|
||||
#include "timer/timer_window.h"
|
||||
#include "viewport_func.h"
|
||||
#include "water.h"
|
||||
#include "window_func.h"
|
||||
#include "window_gui.h"
|
||||
#include "zoom_func.h"
|
||||
|
||||
#include "widgets/company_widget.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "dropdown_common_type.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
||||
/** Company GUI constants. */
|
||||
static void DoSelectCompanyManagerFace(Window *parent);
|
||||
static void ShowCompanyInfrastructure(CompanyID company);
|
||||
|
@ -89,9 +87,7 @@ struct ExpensesList {
|
|||
const StringID title; ///< StringID of list title.
|
||||
const std::initializer_list<ExpensesType> &items; ///< List of expenses types.
|
||||
|
||||
ExpensesList(StringID title, const std::initializer_list<ExpensesType> &list) : title(title), items(list)
|
||||
{
|
||||
}
|
||||
ExpensesList(StringID title, const std::initializer_list<ExpensesType> &list) : title(title), items(list) {}
|
||||
|
||||
uint GetHeight() const
|
||||
{
|
||||
|
@ -112,9 +108,9 @@ struct ExpensesList {
|
|||
|
||||
/** Types of expense lists */
|
||||
static const std::initializer_list<ExpensesList> _expenses_list_types = {
|
||||
{ STR_FINANCES_REVENUE_TITLE, _expenses_list_revenue },
|
||||
{ STR_FINANCES_OPERATING_EXPENSES_TITLE, _expenses_list_operating_costs },
|
||||
{ STR_FINANCES_CAPITAL_EXPENSES_TITLE, _expenses_list_capital_costs },
|
||||
{STR_FINANCES_REVENUE_TITLE, _expenses_list_revenue},
|
||||
{STR_FINANCES_OPERATING_EXPENSES_TITLE, _expenses_list_operating_costs},
|
||||
{STR_FINANCES_CAPITAL_EXPENSES_TITLE, _expenses_list_capital_costs},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -253,7 +249,6 @@ static Money DrawYearCategory(const Rect &r, int start_y, const ExpensesList &li
|
|||
return sum;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw a column with prices.
|
||||
* @param r Available space for drawing.
|
||||
|
@ -396,7 +391,7 @@ struct CompanyFinancesWindow : Window {
|
|||
{
|
||||
switch (widget) {
|
||||
case WID_CF_EXPS_CATEGORY:
|
||||
size.width = GetMaxCategoriesWidth();
|
||||
size.width = GetMaxCategoriesWidth();
|
||||
size.height = GetTotalCategoriesHeight();
|
||||
break;
|
||||
|
||||
|
@ -525,7 +520,9 @@ struct CompanyFinancesWindow : Window {
|
|||
const Company *c = Company::Get(this->window_number);
|
||||
const Expenses &expenses = c->yearly_expenses[NUM_PERIODS - period - 1];
|
||||
/* Show expenses column if it has any non-zero value in it. */
|
||||
if (std::ranges::any_of(expenses, [](const Money &value) { return value != 0; })) {
|
||||
if (std::ranges::any_of(expenses, [](const Money &value) {
|
||||
return value != 0;
|
||||
})) {
|
||||
this->first_visible = period;
|
||||
break;
|
||||
}
|
||||
|
@ -542,24 +539,19 @@ struct CompanyFinancesWindow : Window {
|
|||
* If it has, rescale the window to fit the new amount.
|
||||
*/
|
||||
IntervalTimer<TimerWindow> rescale_interval = {std::chrono::seconds(3), [this](auto) {
|
||||
const Company *c = Company::Get(this->window_number);
|
||||
if (c->money > CompanyFinancesWindow::max_money) {
|
||||
CompanyFinancesWindow::max_money = std::max(c->money * 2, CompanyFinancesWindow::max_money * 4);
|
||||
this->SetupWidgets();
|
||||
this->ReInit();
|
||||
}
|
||||
}};
|
||||
const Company *c = Company::Get(this->window_number);
|
||||
if (c->money > CompanyFinancesWindow::max_money) {
|
||||
CompanyFinancesWindow::max_money = std::max(c->money * 2, CompanyFinancesWindow::max_money * 4);
|
||||
this->SetupWidgets();
|
||||
this->ReInit();
|
||||
}
|
||||
}};
|
||||
};
|
||||
|
||||
/** First conservative estimate of the maximum amount of money */
|
||||
Money CompanyFinancesWindow::max_money = INT32_MAX;
|
||||
|
||||
static WindowDesc _company_finances_desc(
|
||||
WDP_AUTO, "company_finances", 0, 0,
|
||||
WC_FINANCES, WC_NONE,
|
||||
{},
|
||||
_nested_company_finances_widgets
|
||||
);
|
||||
static WindowDesc _company_finances_desc(WDP_AUTO, "company_finances", 0, 0, WC_FINANCES, WC_NONE, {}, _nested_company_finances_widgets);
|
||||
|
||||
/**
|
||||
* Open the finances window of a company.
|
||||
|
@ -577,11 +569,28 @@ void ShowCompanyFinances(CompanyID company)
|
|||
/* Association of liveries to livery classes */
|
||||
static const LiveryClass _livery_class[LS_END] = {
|
||||
LC_OTHER,
|
||||
LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL,
|
||||
LC_ROAD, LC_ROAD,
|
||||
LC_SHIP, LC_SHIP,
|
||||
LC_AIRCRAFT, LC_AIRCRAFT, LC_AIRCRAFT,
|
||||
LC_ROAD, LC_ROAD,
|
||||
LC_RAIL,
|
||||
LC_RAIL,
|
||||
LC_RAIL,
|
||||
LC_RAIL,
|
||||
LC_RAIL,
|
||||
LC_RAIL,
|
||||
LC_RAIL,
|
||||
LC_RAIL,
|
||||
LC_RAIL,
|
||||
LC_RAIL,
|
||||
LC_RAIL,
|
||||
LC_RAIL,
|
||||
LC_RAIL,
|
||||
LC_ROAD,
|
||||
LC_ROAD,
|
||||
LC_SHIP,
|
||||
LC_SHIP,
|
||||
LC_AIRCRAFT,
|
||||
LC_AIRCRAFT,
|
||||
LC_AIRCRAFT,
|
||||
LC_ROAD,
|
||||
LC_ROAD,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -592,7 +601,8 @@ template <SpriteID TSprite = SPR_SQUARE>
|
|||
class DropDownListColourItem : public DropDownIcon<DropDownString<DropDownListItem>> {
|
||||
public:
|
||||
DropDownListColourItem(int colour, bool masked) :
|
||||
DropDownIcon<DropDownString<DropDownListItem>>(TSprite, GetColourPalette(static_cast<Colours>(colour % COLOUR_END)), GetString(colour < COLOUR_END ? (STR_COLOUR_DARK_BLUE + colour) : STR_COLOUR_DEFAULT), colour, masked)
|
||||
DropDownIcon<DropDownString<DropDownListItem>>(
|
||||
TSprite, GetColourPalette(static_cast<Colours>(colour % COLOUR_END)), GetString(colour < COLOUR_END ? (STR_COLOUR_DARK_BLUE + colour) : STR_COLOUR_DEFAULT), colour, masked)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -719,11 +729,20 @@ public:
|
|||
this->RaiseWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
|
||||
const Group *g = Group::Get(group);
|
||||
switch (g->vehicle_type) {
|
||||
case VEH_TRAIN: this->livery_class = LC_GROUP_RAIL; break;
|
||||
case VEH_ROAD: this->livery_class = LC_GROUP_ROAD; break;
|
||||
case VEH_SHIP: this->livery_class = LC_GROUP_SHIP; break;
|
||||
case VEH_AIRCRAFT: this->livery_class = LC_GROUP_AIRCRAFT; break;
|
||||
default: NOT_REACHED();
|
||||
case VEH_TRAIN:
|
||||
this->livery_class = LC_GROUP_RAIL;
|
||||
break;
|
||||
case VEH_ROAD:
|
||||
this->livery_class = LC_GROUP_ROAD;
|
||||
break;
|
||||
case VEH_SHIP:
|
||||
this->livery_class = LC_GROUP_SHIP;
|
||||
break;
|
||||
case VEH_AIRCRAFT:
|
||||
this->livery_class = LC_GROUP_AIRCRAFT;
|
||||
break;
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
this->sel = group.base();
|
||||
this->LowerWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
|
||||
|
@ -871,7 +890,7 @@ public:
|
|||
|
||||
Rect ir = r.WithHeight(this->resize.step_height).Shrink(WidgetDimensions::scaled.matrix);
|
||||
int square_offs = (ir.Height() - this->square.height) / 2;
|
||||
int text_offs = (ir.Height() - GetCharacterHeight(FS_NORMAL)) / 2;
|
||||
int text_offs = (ir.Height() - GetCharacterHeight(FS_NORMAL)) / 2;
|
||||
|
||||
int y = ir.top;
|
||||
|
||||
|
@ -882,12 +901,14 @@ public:
|
|||
|
||||
/* Text below the first dropdown. */
|
||||
DrawSprite(SPR_SQUARE, GetColourPalette(livery.colour1), pri_squ.left, y + square_offs);
|
||||
DrawString(pri.left, pri.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 0)) ? STR_COLOUR_DARK_BLUE + livery.colour1 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
|
||||
DrawString(
|
||||
pri.left, pri.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 0)) ? STR_COLOUR_DARK_BLUE + livery.colour1 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
|
||||
|
||||
/* Text below the second dropdown. */
|
||||
if (sec.right > sec.left) { // Second dropdown has non-zero size.
|
||||
DrawSprite(SPR_SQUARE, GetColourPalette(livery.colour2), sec_squ.left, y + square_offs);
|
||||
DrawString(sec.left, sec.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 1)) ? STR_COLOUR_DARK_BLUE + livery.colour2 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
|
||||
DrawString(
|
||||
sec.left, sec.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 1)) ? STR_COLOUR_DARK_BLUE + livery.colour2 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
|
||||
}
|
||||
|
||||
y += this->line_height;
|
||||
|
@ -911,7 +932,7 @@ public:
|
|||
}
|
||||
|
||||
if (this->vscroll->GetCount() == 0) {
|
||||
const StringID empty_labels[] = { STR_LIVERY_TRAIN_GROUP_EMPTY, STR_LIVERY_ROAD_VEHICLE_GROUP_EMPTY, STR_LIVERY_SHIP_GROUP_EMPTY, STR_LIVERY_AIRCRAFT_GROUP_EMPTY };
|
||||
const StringID empty_labels[] = {STR_LIVERY_TRAIN_GROUP_EMPTY, STR_LIVERY_ROAD_VEHICLE_GROUP_EMPTY, STR_LIVERY_SHIP_GROUP_EMPTY, STR_LIVERY_AIRCRAFT_GROUP_EMPTY};
|
||||
VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);
|
||||
DrawString(ir.left, ir.right, y + text_offs, empty_labels[vtype], TC_BLACK);
|
||||
}
|
||||
|
@ -1103,12 +1124,7 @@ static constexpr NWidgetPart _nested_select_company_livery_widgets[] = {
|
|||
};
|
||||
/* clang-format on */
|
||||
|
||||
static WindowDesc _select_company_livery_desc(
|
||||
WDP_AUTO, "company_color_scheme", 0, 0,
|
||||
WC_COMPANY_COLOUR, WC_NONE,
|
||||
{},
|
||||
_nested_select_company_livery_widgets
|
||||
);
|
||||
static WindowDesc _select_company_livery_desc(WDP_AUTO, "company_color_scheme", 0, 0, WC_COMPANY_COLOUR, WC_NONE, {}, _nested_select_company_livery_widgets);
|
||||
|
||||
void ShowCompanyLiveryWindow(CompanyID company, GroupID group)
|
||||
{
|
||||
|
@ -1135,9 +1151,9 @@ void DrawCompanyManagerFace(CompanyManagerFace cmf, Colours colour, const Rect &
|
|||
int x = CentreBounds(r.left, r.right, d.width);
|
||||
int y = CentreBounds(r.top, r.bottom, d.height);
|
||||
|
||||
bool has_moustache = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge) != 0;
|
||||
bool has_moustache = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge) != 0;
|
||||
bool has_tie_earring = !HasBit(ge, GENDER_FEMALE) || GetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge) != 0;
|
||||
bool has_glasses = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
|
||||
bool has_glasses = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
|
||||
PaletteID pal;
|
||||
|
||||
/* Modify eye colour palette only if 2 or more valid values exist */
|
||||
|
@ -1145,10 +1161,17 @@ void DrawCompanyManagerFace(CompanyManagerFace cmf, Colours colour, const Rect &
|
|||
pal = PAL_NONE;
|
||||
} else {
|
||||
switch (GetCompanyManagerFaceBits(cmf, CMFV_EYE_COLOUR, ge)) {
|
||||
default: NOT_REACHED();
|
||||
case 0: pal = PALETTE_TO_BROWN; break;
|
||||
case 1: pal = PALETTE_TO_BLUE; break;
|
||||
case 2: pal = PALETTE_TO_GREEN; break;
|
||||
default:
|
||||
NOT_REACHED();
|
||||
case 0:
|
||||
pal = PALETTE_TO_BROWN;
|
||||
break;
|
||||
case 1:
|
||||
pal = PALETTE_TO_BLUE;
|
||||
break;
|
||||
case 2:
|
||||
pal = PALETTE_TO_GREEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1157,12 +1180,21 @@ void DrawCompanyManagerFace(CompanyManagerFace cmf, Colours colour, const Rect &
|
|||
|
||||
for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
|
||||
switch (cmfv) {
|
||||
case CMFV_MOUSTACHE: if (!has_moustache) continue; break;
|
||||
case CMFV_MOUSTACHE:
|
||||
if (!has_moustache) continue;
|
||||
break;
|
||||
case CMFV_LIPS:
|
||||
case CMFV_NOSE: if (has_moustache) continue; break;
|
||||
case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
|
||||
case CMFV_GLASSES: if (!has_glasses) continue; break;
|
||||
default: break;
|
||||
case CMFV_NOSE:
|
||||
if (has_moustache) continue;
|
||||
break;
|
||||
case CMFV_TIE_EARRING:
|
||||
if (!has_tie_earring) continue;
|
||||
break;
|
||||
case CMFV_GLASSES:
|
||||
if (!has_glasses) continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DrawSprite(GetCompanyManagerFaceSprite(cmf, cmfv, ge), (cmfv == CMFV_EYEBROWS) ? pal : PAL_NONE, x, y);
|
||||
}
|
||||
|
@ -1328,16 +1360,15 @@ static constexpr NWidgetPart _nested_select_company_manager_face_widgets[] = {
|
|||
/* clang-format on */
|
||||
|
||||
/** Management class for customizing the face of the company manager. */
|
||||
class SelectCompanyManagerFaceWindow : public Window
|
||||
{
|
||||
class SelectCompanyManagerFaceWindow : public Window {
|
||||
CompanyManagerFace face{}; ///< company manager face bits
|
||||
bool advanced = false; ///< advanced company manager face selection window
|
||||
|
||||
GenderEthnicity ge{}; ///< Gender and ethnicity.
|
||||
bool is_female = false; ///< Female face.
|
||||
bool is_female = false; ///< Female face.
|
||||
bool is_moust_male = false; ///< Male face with a moustache.
|
||||
|
||||
Dimension yesno_dim{}; ///< Dimension of a yes/no button of a part in the advanced face window.
|
||||
Dimension yesno_dim{}; ///< Dimension of a yes/no button of a part in the advanced face window.
|
||||
Dimension number_dim{}; ///< Dimension of a number widget of a part in the advanced face window.
|
||||
|
||||
/**
|
||||
|
@ -1407,7 +1438,7 @@ public:
|
|||
{
|
||||
/* Size of the boolean yes/no button. */
|
||||
Dimension yesno_dim = maxdim(GetStringBoundingBox(STR_FACE_YES), GetStringBoundingBox(STR_FACE_NO));
|
||||
yesno_dim.width += WidgetDimensions::scaled.framerect.Horizontal();
|
||||
yesno_dim.width += WidgetDimensions::scaled.framerect.Horizontal();
|
||||
yesno_dim.height += WidgetDimensions::scaled.framerect.Vertical();
|
||||
/* Size of the number button + arrows. */
|
||||
Dimension number_dim = {0, 0};
|
||||
|
@ -1471,59 +1502,50 @@ public:
|
|||
{
|
||||
/* lower the non-selected gender button */
|
||||
this->SetWidgetsLoweredState(!this->is_female, WID_SCMF_MALE, WID_SCMF_MALE2);
|
||||
this->SetWidgetsLoweredState( this->is_female, WID_SCMF_FEMALE, WID_SCMF_FEMALE2);
|
||||
this->SetWidgetsLoweredState(this->is_female, WID_SCMF_FEMALE, WID_SCMF_FEMALE2);
|
||||
|
||||
/* advanced company manager face selection window */
|
||||
|
||||
/* lower the non-selected ethnicity button */
|
||||
this->SetWidgetLoweredState(WID_SCMF_ETHNICITY_EUR, !HasBit(this->ge, ETHNICITY_BLACK));
|
||||
this->SetWidgetLoweredState(WID_SCMF_ETHNICITY_AFR, HasBit(this->ge, ETHNICITY_BLACK));
|
||||
|
||||
this->SetWidgetLoweredState(WID_SCMF_ETHNICITY_AFR, HasBit(this->ge, ETHNICITY_BLACK));
|
||||
|
||||
/* Disable dynamically the widgets which CompanyManagerFaceVariable has less than 2 options
|
||||
* (or in other words you haven't any choice).
|
||||
* If the widgets depend on a HAS-variable and this is false the widgets will be disabled, too. */
|
||||
|
||||
/* Eye colour buttons */
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_EYE_COLOUR].valid_values[this->ge] < 2,
|
||||
WID_SCMF_EYECOLOUR, WID_SCMF_EYECOLOUR_L, WID_SCMF_EYECOLOUR_R);
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_EYE_COLOUR].valid_values[this->ge] < 2, WID_SCMF_EYECOLOUR, WID_SCMF_EYECOLOUR_L, WID_SCMF_EYECOLOUR_R);
|
||||
|
||||
/* Chin buttons */
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_CHIN].valid_values[this->ge] < 2,
|
||||
WID_SCMF_CHIN, WID_SCMF_CHIN_L, WID_SCMF_CHIN_R);
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_CHIN].valid_values[this->ge] < 2, WID_SCMF_CHIN, WID_SCMF_CHIN_L, WID_SCMF_CHIN_R);
|
||||
|
||||
/* Eyebrows buttons */
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_EYEBROWS].valid_values[this->ge] < 2,
|
||||
WID_SCMF_EYEBROWS, WID_SCMF_EYEBROWS_L, WID_SCMF_EYEBROWS_R);
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_EYEBROWS].valid_values[this->ge] < 2, WID_SCMF_EYEBROWS, WID_SCMF_EYEBROWS_L, WID_SCMF_EYEBROWS_R);
|
||||
|
||||
/* Lips or (if it a male face with a moustache) moustache buttons */
|
||||
this->SetWidgetsDisabledState(_cmf_info[this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS].valid_values[this->ge] < 2,
|
||||
WID_SCMF_LIPS_MOUSTACHE, WID_SCMF_LIPS_MOUSTACHE_L, WID_SCMF_LIPS_MOUSTACHE_R);
|
||||
this->SetWidgetsDisabledState(
|
||||
_cmf_info[this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS].valid_values[this->ge] < 2, WID_SCMF_LIPS_MOUSTACHE, WID_SCMF_LIPS_MOUSTACHE_L, WID_SCMF_LIPS_MOUSTACHE_R);
|
||||
|
||||
/* Nose buttons | male faces with moustache haven't any nose options */
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_NOSE].valid_values[this->ge] < 2 || this->is_moust_male,
|
||||
WID_SCMF_NOSE, WID_SCMF_NOSE_L, WID_SCMF_NOSE_R);
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_NOSE].valid_values[this->ge] < 2 || this->is_moust_male, WID_SCMF_NOSE, WID_SCMF_NOSE_L, WID_SCMF_NOSE_R);
|
||||
|
||||
/* Hair buttons */
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_HAIR].valid_values[this->ge] < 2,
|
||||
WID_SCMF_HAIR, WID_SCMF_HAIR_L, WID_SCMF_HAIR_R);
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_HAIR].valid_values[this->ge] < 2, WID_SCMF_HAIR, WID_SCMF_HAIR_L, WID_SCMF_HAIR_R);
|
||||
|
||||
/* Jacket buttons */
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_JACKET].valid_values[this->ge] < 2,
|
||||
WID_SCMF_JACKET, WID_SCMF_JACKET_L, WID_SCMF_JACKET_R);
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_JACKET].valid_values[this->ge] < 2, WID_SCMF_JACKET, WID_SCMF_JACKET_L, WID_SCMF_JACKET_R);
|
||||
|
||||
/* Collar buttons */
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_COLLAR].valid_values[this->ge] < 2,
|
||||
WID_SCMF_COLLAR, WID_SCMF_COLLAR_L, WID_SCMF_COLLAR_R);
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_COLLAR].valid_values[this->ge] < 2, WID_SCMF_COLLAR, WID_SCMF_COLLAR_L, WID_SCMF_COLLAR_R);
|
||||
|
||||
/* Tie/earring buttons | female faces without earring haven't any earring options */
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_TIE_EARRING].valid_values[this->ge] < 2 ||
|
||||
(this->is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge) == 0),
|
||||
WID_SCMF_TIE_EARRING, WID_SCMF_TIE_EARRING_L, WID_SCMF_TIE_EARRING_R);
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_TIE_EARRING].valid_values[this->ge] < 2 || (this->is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge) == 0),
|
||||
WID_SCMF_TIE_EARRING, WID_SCMF_TIE_EARRING_L, WID_SCMF_TIE_EARRING_R);
|
||||
|
||||
/* Glasses buttons | faces without glasses haven't any glasses options */
|
||||
this->SetWidgetsDisabledState(_cmf_info[CMFV_GLASSES].valid_values[this->ge] < 2 || GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge) == 0,
|
||||
WID_SCMF_GLASSES, WID_SCMF_GLASSES_L, WID_SCMF_GLASSES_R);
|
||||
this->SetWidgetsDisabledState(
|
||||
_cmf_info[CMFV_GLASSES].valid_values[this->ge] < 2 || GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge) == 0, WID_SCMF_GLASSES, WID_SCMF_GLASSES_L, WID_SCMF_GLASSES_R);
|
||||
|
||||
this->DrawWidgets();
|
||||
}
|
||||
|
@ -1545,31 +1567,31 @@ public:
|
|||
}
|
||||
|
||||
case WID_SCMF_HAS_GLASSES:
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge), true );
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge), true);
|
||||
|
||||
case WID_SCMF_HAIR:
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_HAIR, this->ge), false);
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_HAIR, this->ge), false);
|
||||
|
||||
case WID_SCMF_EYEBROWS:
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_EYEBROWS, this->ge), false);
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_EYEBROWS, this->ge), false);
|
||||
|
||||
case WID_SCMF_EYECOLOUR:
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_EYE_COLOUR, this->ge), false);
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_EYE_COLOUR, this->ge), false);
|
||||
|
||||
case WID_SCMF_GLASSES:
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_GLASSES, this->ge), false);
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_GLASSES, this->ge), false);
|
||||
|
||||
case WID_SCMF_NOSE:
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_NOSE, this->ge), false);
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_NOSE, this->ge), false);
|
||||
|
||||
case WID_SCMF_CHIN:
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_CHIN, this->ge), false);
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_CHIN, this->ge), false);
|
||||
|
||||
case WID_SCMF_JACKET:
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_JACKET, this->ge), false);
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_JACKET, this->ge), false);
|
||||
|
||||
case WID_SCMF_COLLAR:
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_COLLAR, this->ge), false);
|
||||
return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_COLLAR, this->ge), false);
|
||||
|
||||
default:
|
||||
return this->Window::GetWidgetString(widget, stringid);
|
||||
|
@ -1663,25 +1685,51 @@ public:
|
|||
|
||||
if (widget < WID_SCMF_EYECOLOUR_L) { // Bool buttons
|
||||
switch (widget - WID_SCMF_HAS_MOUSTACHE_EARRING) {
|
||||
default: NOT_REACHED();
|
||||
case 0: cmfv = this->is_female ? CMFV_HAS_TIE_EARRING : CMFV_HAS_MOUSTACHE; break; // Has earring/moustache button
|
||||
case 1: cmfv = CMFV_HAS_GLASSES; break; // Has glasses button
|
||||
default:
|
||||
NOT_REACHED();
|
||||
case 0:
|
||||
cmfv = this->is_female ? CMFV_HAS_TIE_EARRING : CMFV_HAS_MOUSTACHE;
|
||||
break; // Has earring/moustache button
|
||||
case 1:
|
||||
cmfv = CMFV_HAS_GLASSES;
|
||||
break; // Has glasses button
|
||||
}
|
||||
SetCompanyManagerFaceBits(this->face, cmfv, this->ge, !GetCompanyManagerFaceBits(this->face, cmfv, this->ge));
|
||||
ScaleAllCompanyManagerFaceBits(this->face);
|
||||
} else { // Value buttons
|
||||
switch ((widget - WID_SCMF_EYECOLOUR_L) / 3) {
|
||||
default: NOT_REACHED();
|
||||
case 0: cmfv = CMFV_EYE_COLOUR; break; // Eye colour buttons
|
||||
case 1: cmfv = CMFV_CHIN; break; // Chin buttons
|
||||
case 2: cmfv = CMFV_EYEBROWS; break; // Eyebrows buttons
|
||||
case 3: cmfv = this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS; break; // Moustache or lips buttons
|
||||
case 4: cmfv = CMFV_NOSE; break; // Nose buttons
|
||||
case 5: cmfv = CMFV_HAIR; break; // Hair buttons
|
||||
case 6: cmfv = CMFV_JACKET; break; // Jacket buttons
|
||||
case 7: cmfv = CMFV_COLLAR; break; // Collar buttons
|
||||
case 8: cmfv = CMFV_TIE_EARRING; break; // Tie/earring buttons
|
||||
case 9: cmfv = CMFV_GLASSES; break; // Glasses buttons
|
||||
default:
|
||||
NOT_REACHED();
|
||||
case 0:
|
||||
cmfv = CMFV_EYE_COLOUR;
|
||||
break; // Eye colour buttons
|
||||
case 1:
|
||||
cmfv = CMFV_CHIN;
|
||||
break; // Chin buttons
|
||||
case 2:
|
||||
cmfv = CMFV_EYEBROWS;
|
||||
break; // Eyebrows buttons
|
||||
case 3:
|
||||
cmfv = this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS;
|
||||
break; // Moustache or lips buttons
|
||||
case 4:
|
||||
cmfv = CMFV_NOSE;
|
||||
break; // Nose buttons
|
||||
case 5:
|
||||
cmfv = CMFV_HAIR;
|
||||
break; // Hair buttons
|
||||
case 6:
|
||||
cmfv = CMFV_JACKET;
|
||||
break; // Jacket buttons
|
||||
case 7:
|
||||
cmfv = CMFV_COLLAR;
|
||||
break; // Collar buttons
|
||||
case 8:
|
||||
cmfv = CMFV_TIE_EARRING;
|
||||
break; // Tie/earring buttons
|
||||
case 9:
|
||||
cmfv = CMFV_GLASSES;
|
||||
break; // Glasses buttons
|
||||
}
|
||||
/* 0 == left (_L), 1 == middle or 2 == right (_R) - button click */
|
||||
IncreaseCompanyManagerFaceBits(this->face, cmfv, this->ge, (((widget - WID_SCMF_EYECOLOUR_L) % 3) != 0) ? 1 : -1);
|
||||
|
@ -1710,12 +1758,7 @@ public:
|
|||
};
|
||||
|
||||
/** Company manager face selection window description */
|
||||
static WindowDesc _select_company_manager_face_desc(
|
||||
WDP_AUTO, nullptr, 0, 0,
|
||||
WC_COMPANY_MANAGER_FACE, WC_NONE,
|
||||
WindowDefaultFlag::Construction,
|
||||
_nested_select_company_manager_face_widgets
|
||||
);
|
||||
static WindowDesc _select_company_manager_face_desc(WDP_AUTO, nullptr, 0, 0, WC_COMPANY_MANAGER_FACE, WC_NONE, WindowDefaultFlag::Construction, _nested_select_company_manager_face_widgets);
|
||||
|
||||
/**
|
||||
* Open the simple/advanced company manager face selection window
|
||||
|
@ -1754,8 +1797,7 @@ static constexpr NWidgetPart _nested_company_infrastructure_widgets[] = {
|
|||
/**
|
||||
* Window with detailed information about the company's infrastructure.
|
||||
*/
|
||||
struct CompanyInfrastructureWindow : Window
|
||||
{
|
||||
struct CompanyInfrastructureWindow : Window {
|
||||
enum class InfrastructureItemType : uint8_t {
|
||||
Header, ///< Section header.
|
||||
Spacer, ///< Spacer
|
||||
|
@ -1941,7 +1983,8 @@ struct CompanyInfrastructureWindow : Window
|
|||
this->count_width = GetStringBoundingBox(GetString(STR_JUST_COMMA, max_count)).width;
|
||||
|
||||
if (_settings_game.economy.infrastructure_maintenance) {
|
||||
this->cost_width = GetStringBoundingBox(GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, max_cost)).width;
|
||||
this->cost_width =
|
||||
GetStringBoundingBox(GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, max_cost)).width;
|
||||
} else {
|
||||
this->cost_width = 0;
|
||||
}
|
||||
|
@ -1978,14 +2021,16 @@ struct CompanyInfrastructureWindow : Window
|
|||
case InfrastructureItemType::Total:
|
||||
/* Draw line in the spacer above the total. */
|
||||
GfxFillRect(costr.Translate(0, -WidgetDimensions::scaled.vsep_normal).WithHeight(WidgetDimensions::scaled.fullbevel.top), PC_WHITE);
|
||||
DrawString(costr, GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, it->cost * 12), TC_BLACK, SA_RIGHT | SA_FORCE);
|
||||
DrawString(costr, GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, it->cost * 12),
|
||||
TC_BLACK, SA_RIGHT | SA_FORCE);
|
||||
break;
|
||||
|
||||
case InfrastructureItemType::Value:
|
||||
DrawString(labelr.Indent(WidgetDimensions::scaled.hsep_indent, rtl), GetString(it->label), TC_WHITE);
|
||||
DrawString(countr, GetString(STR_JUST_COMMA, it->count), TC_WHITE, SA_RIGHT | SA_FORCE);
|
||||
if (_settings_game.economy.infrastructure_maintenance) {
|
||||
DrawString(costr, GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, it->cost * 12), TC_BLACK, SA_RIGHT | SA_FORCE);
|
||||
DrawString(costr, GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, it->cost * 12),
|
||||
TC_BLACK, SA_RIGHT | SA_FORCE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1997,9 +2042,9 @@ struct CompanyInfrastructureWindow : Window
|
|||
}
|
||||
|
||||
IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(1), [this](auto) {
|
||||
this->UpdateInfrastructureList();
|
||||
this->SetWidgetDirty(WID_CI_LIST);
|
||||
}};
|
||||
this->UpdateInfrastructureList();
|
||||
this->SetWidgetDirty(WID_CI_LIST);
|
||||
}};
|
||||
|
||||
void OnResize() override
|
||||
{
|
||||
|
@ -2019,12 +2064,7 @@ struct CompanyInfrastructureWindow : Window
|
|||
}
|
||||
};
|
||||
|
||||
static WindowDesc _company_infrastructure_desc(
|
||||
WDP_AUTO, "company_infrastructure", 0, 0,
|
||||
WC_COMPANY_INFRASTRUCTURE, WC_NONE,
|
||||
{},
|
||||
_nested_company_infrastructure_widgets
|
||||
);
|
||||
static WindowDesc _company_infrastructure_desc(WDP_AUTO, "company_infrastructure", 0, 0, WC_COMPANY_INFRASTRUCTURE, WC_NONE, {}, _nested_company_infrastructure_widgets);
|
||||
|
||||
/**
|
||||
* Open the infrastructure window of a company.
|
||||
|
@ -2115,26 +2155,23 @@ static constexpr NWidgetPart _nested_company_widgets[] = {
|
|||
/* clang-format on */
|
||||
|
||||
/** Strings for the company vehicle counts */
|
||||
static const StringID _company_view_vehicle_count_strings[] = {
|
||||
STR_COMPANY_VIEW_TRAINS, STR_COMPANY_VIEW_ROAD_VEHICLES, STR_COMPANY_VIEW_SHIPS, STR_COMPANY_VIEW_AIRCRAFT
|
||||
};
|
||||
static const StringID _company_view_vehicle_count_strings[] = {STR_COMPANY_VIEW_TRAINS, STR_COMPANY_VIEW_ROAD_VEHICLES, STR_COMPANY_VIEW_SHIPS, STR_COMPANY_VIEW_AIRCRAFT};
|
||||
|
||||
/**
|
||||
* Window with general information about a company
|
||||
*/
|
||||
struct CompanyWindow : Window
|
||||
{
|
||||
struct CompanyWindow : Window {
|
||||
CompanyWidgets query_widget{};
|
||||
|
||||
/** Display planes in the company window. */
|
||||
enum CompanyWindowPlanes : uint8_t {
|
||||
/* Display planes of the #WID_C_SELECT_VIEW_BUILD_HQ selection widget. */
|
||||
CWP_VB_VIEW = 0, ///< Display the view button
|
||||
CWP_VB_BUILD, ///< Display the build button
|
||||
CWP_VB_VIEW = 0, ///< Display the view button
|
||||
CWP_VB_BUILD, ///< Display the build button
|
||||
|
||||
/* Display planes of the #WID_C_SELECT_RELOCATE selection widget. */
|
||||
CWP_RELOCATE_SHOW = 0, ///< Show the relocate HQ button.
|
||||
CWP_RELOCATE_HIDE, ///< Hide the relocate HQ button.
|
||||
CWP_RELOCATE_HIDE, ///< Hide the relocate HQ button.
|
||||
};
|
||||
|
||||
CompanyWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc)
|
||||
|
@ -2168,7 +2205,8 @@ struct CompanyWindow : Window
|
|||
reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_HOSTILE_TAKEOVER)->SetDisplayedPlane((local || _local_company == COMPANY_SPECTATOR || !c->is_ai || _networking) ? SZSP_NONE : 0);
|
||||
|
||||
/* Multiplayer buttons. */
|
||||
reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_MULTIPLAYER)->SetDisplayedPlane((!_networking || !NetworkCanJoinCompany(c->index) || _local_company == c->index) ? (int)SZSP_NONE : 0);
|
||||
reinit |=
|
||||
this->GetWidget<NWidgetStacked>(WID_C_SELECT_MULTIPLAYER)->SetDisplayedPlane((!_networking || !NetworkCanJoinCompany(c->index) || _local_company == c->index) ? (int)SZSP_NONE : 0);
|
||||
|
||||
this->SetWidgetDisabledState(WID_C_COMPANY_JOIN, c->is_ai);
|
||||
|
||||
|
@ -2360,7 +2398,9 @@ struct CompanyWindow : Window
|
|||
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_C_NEW_FACE: DoSelectCompanyManagerFace(this); break;
|
||||
case WID_C_NEW_FACE:
|
||||
DoSelectCompanyManagerFace(this);
|
||||
break;
|
||||
|
||||
case WID_C_COLOUR_SCHEME:
|
||||
ShowCompanyLiveryWindow(this->window_number, GroupID::Invalid());
|
||||
|
@ -2368,12 +2408,14 @@ struct CompanyWindow : Window
|
|||
|
||||
case WID_C_PRESIDENT_NAME:
|
||||
this->query_widget = WID_C_PRESIDENT_NAME;
|
||||
ShowQueryString(GetString(STR_PRESIDENT_NAME, this->window_number), STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION, MAX_LENGTH_PRESIDENT_NAME_CHARS, this, CS_ALPHANUMERAL, {QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars});
|
||||
ShowQueryString(GetString(STR_PRESIDENT_NAME, this->window_number), STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION, MAX_LENGTH_PRESIDENT_NAME_CHARS, this, CS_ALPHANUMERAL,
|
||||
{QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars});
|
||||
break;
|
||||
|
||||
case WID_C_COMPANY_NAME:
|
||||
this->query_widget = WID_C_COMPANY_NAME;
|
||||
ShowQueryString(GetString(STR_COMPANY_NAME, this->window_number), STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION, MAX_LENGTH_COMPANY_NAME_CHARS, this, CS_ALPHANUMERAL, {QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars});
|
||||
ShowQueryString(GetString(STR_COMPANY_NAME, this->window_number), STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION, MAX_LENGTH_COMPANY_NAME_CHARS, this, CS_ALPHANUMERAL,
|
||||
{QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars});
|
||||
break;
|
||||
|
||||
case WID_C_VIEW_HQ: {
|
||||
|
@ -2441,8 +2483,8 @@ struct CompanyWindow : Window
|
|||
|
||||
/** Redraw the window on a regular interval. */
|
||||
IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(3), [this](auto) {
|
||||
this->SetDirty();
|
||||
}};
|
||||
this->SetDirty();
|
||||
}};
|
||||
|
||||
void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
|
||||
{
|
||||
|
@ -2462,7 +2504,8 @@ struct CompanyWindow : Window
|
|||
if (!str.has_value()) return;
|
||||
|
||||
switch (this->query_widget) {
|
||||
default: NOT_REACHED();
|
||||
default:
|
||||
NOT_REACHED();
|
||||
|
||||
case WID_C_GIVE_MONEY: {
|
||||
Money money = std::strtoull(str->c_str(), nullptr, 10) / GetCurrency().rate;
|
||||
|
@ -2489,12 +2532,7 @@ struct CompanyWindow : Window
|
|||
}
|
||||
};
|
||||
|
||||
static WindowDesc _company_desc(
|
||||
WDP_AUTO, "company", 0, 0,
|
||||
WC_COMPANY, WC_NONE,
|
||||
{},
|
||||
_nested_company_widgets
|
||||
);
|
||||
static WindowDesc _company_desc(WDP_AUTO, "company", 0, 0, WC_COMPANY, WC_NONE, {}, _nested_company_widgets);
|
||||
|
||||
/**
|
||||
* Show the window with the overview of the company.
|
||||
|
@ -2585,16 +2623,16 @@ struct BuyCompanyWindow : Window {
|
|||
* Check on a regular interval if the company value has changed.
|
||||
*/
|
||||
IntervalTimer<TimerWindow> rescale_interval = {std::chrono::seconds(3), [this](auto) {
|
||||
/* Value can't change when in bankruptcy. */
|
||||
if (!this->hostile_takeover) return;
|
||||
/* Value can't change when in bankruptcy. */
|
||||
if (!this->hostile_takeover) return;
|
||||
|
||||
const Company *c = Company::Get(this->window_number);
|
||||
auto new_value = CalculateHostileTakeoverValue(c);
|
||||
if (new_value != this->company_value) {
|
||||
this->company_value = new_value;
|
||||
this->ReInit();
|
||||
}
|
||||
}};
|
||||
const Company *c = Company::Get(this->window_number);
|
||||
auto new_value = CalculateHostileTakeoverValue(c);
|
||||
if (new_value != this->company_value) {
|
||||
this->company_value = new_value;
|
||||
this->ReInit();
|
||||
}
|
||||
}};
|
||||
|
||||
private:
|
||||
bool hostile_takeover = false; ///< Whether the window is showing a hostile takeover.
|
||||
|
@ -2622,12 +2660,7 @@ static constexpr NWidgetPart _nested_buy_company_widgets[] = {
|
|||
};
|
||||
/* clang-format on */
|
||||
|
||||
static WindowDesc _buy_company_desc(
|
||||
WDP_AUTO, nullptr, 0, 0,
|
||||
WC_BUY_COMPANY, WC_NONE,
|
||||
WindowDefaultFlag::Construction,
|
||||
_nested_buy_company_widgets
|
||||
);
|
||||
static WindowDesc _buy_company_desc(WDP_AUTO, nullptr, 0, 0, WC_BUY_COMPANY, WC_NONE, WindowDefaultFlag::Construction, _nested_buy_company_widgets);
|
||||
|
||||
/**
|
||||
* Show the query to buy another company.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue