1
0
Fork 0

Compare commits

...

8 Commits

Author SHA1 Message Date
Loïc Guilloux fa32464b6a
Merge 185ca3a7f5 into 9ce2aca949 2025-07-14 18:19:40 +00:00
Peter Nelson 9ce2aca949 Codechange: Get/pass ScriptStorage by reference instead of pointer. 2025-07-14 19:19:29 +01:00
Peter Nelson 55098a2f2e Codechange: Get/pass engine by reference instead of pointer. 2025-07-14 19:19:29 +01:00
Peter Nelson 7ff0c67f77 Codechange: Get/pass script controller by reference instead of pointer. 2025-07-14 19:19:29 +01:00
Peter Nelson b2de1ff66f
Fix #14433: Broken road stop drawing due to incorrect modes conversion. (#14434)
The mask was treated as a single RoadStopDrawMode instead of a RoadStopDrawModes bitset.
2025-07-14 17:25:53 +01:00
Loïc Guilloux fc924161ab
Fix 0455627d: Don't draw timetable panel if no orders (#14441) 2025-07-14 14:18:54 +00:00
Peter Nelson 61a299bc99
Codechange: Use SpriteID as GlyphID for SpriteFontCache. (#14439)
This reduces the amount of lookups in the character map as rendering a cached layout no longer needs to do so.
2025-07-14 13:28:10 +01:00
glx22 185ca3a7f5 Change: [Script] Replace ScriptDate with ScriptEconomyDate and ScriptCalendarDate 2025-05-24 23:23:48 +02:00
34 changed files with 593 additions and 199 deletions

View File

@ -7,6 +7,19 @@
/* This file contains code to downgrade the API from 15 to 14. */ /* This file contains code to downgrade the API from 15 to 14. */
AIDate <- AIEconomyDate;
AIDate.IsValidDate <- function(date) { return AIDate(date).IsValid(); }
AIDate.GetCurrentDateCompat14 <- AIDate.GetCurrentDate;
AIDate.GetCurrentDate <- function() { return AIDate.GetCurrentDateCompat14().date(); }
AIDate.GetYearCompat14 <- AIDate.GetYear;
AIDate.GetYear <- function(date) { return AIDate(date).GetYearCompat14(); }
AIDate.GetMonthCompat14 <- AIDate.GetMonth;
AIDate.GetMonth <- function(date) { return AIDate(date).GetMonthCompat14(); }
AIDate.GetDayOfMonthCompat14 <- AIDate.GetDayOfMonth;
AIDate.GetDayOfMonth <- function(date) { return AIDate(date).GetDayOfMonthCompat14(); }
AIDate.GetDateCompat14 <- AIDate.GetDate;
AIDate.GetDate <- function(year, month, day) { return AIDate.GetDateCompat14(year, month, day).date(); }
AIBridge.GetBridgeID <- AIBridge.GetBridgeType; AIBridge.GetBridgeID <- AIBridge.GetBridgeType;
class AICompat14 { class AICompat14 {
@ -17,6 +30,8 @@ class AICompat14 {
} }
} }
AIBaseStation.GetConstructionDateCompat14 <- AIBaseStation.GetConstructionDate;
AIBaseStation.GetConstructionDate <- function(station_id) { return AIBaseStation.GetConstructionDateCompat14(station_id).date(); }
AIBaseStation.SetNameCompat14 <- AIBaseStation.SetName; AIBaseStation.SetNameCompat14 <- AIBaseStation.SetName;
AIBaseStation.SetName <- function(id, name) { return AIBaseStation.SetNameCompat14(id, AICompat14.Text(name)); } AIBaseStation.SetName <- function(id, name) { return AIBaseStation.SetNameCompat14(id, AICompat14.Text(name)); }
@ -25,12 +40,18 @@ AICompany.SetName <- function(name) { return AICompany.SetNameCompat14(AICompat1
AICompany.SetPresidentNameCompat14 <- AICompany.SetPresidentName; AICompany.SetPresidentNameCompat14 <- AICompany.SetPresidentName;
AICompany.SetPresidentName <- function(name) { return AICompany.SetPresidentNameCompat14(AICompat14.Text(name)); } AICompany.SetPresidentName <- function(name) { return AICompany.SetPresidentNameCompat14(AICompat14.Text(name)); }
AIEngine.GetDesignDateCompat14 <- AIEngine.GetDesignDate;
AIEngine.GetDesignDate <- function(engine_id) { return AIEngine.GetDesignDateCompat14(engine_id).date(); }
AIGroup.SetNameCompat14 <- AIGroup.SetName; AIGroup.SetNameCompat14 <- AIGroup.SetName;
AIGroup.SetName <- function(id, name) { return AIGroup.SetNameCompat14(id, AICompat14.Text(name)); } AIGroup.SetName <- function(id, name) { return AIGroup.SetNameCompat14(id, AICompat14.Text(name)); }
AISign.BuildSignCompat14 <- AISign.BuildSign; AISign.BuildSignCompat14 <- AISign.BuildSign;
AISign.BuildSign <- function(id, name) { return AISign.BuildSignCompat14(id, AICompat14.Text(name)); } AISign.BuildSign <- function(id, name) { return AISign.BuildSignCompat14(id, AICompat14.Text(name)); }
AISubsidy.GetExpireDateCompat14 <- AISubsidy.GetExpireDate;
AISubsidy.GetExpireDate <- function(subsidy_id) { return AISubsidy.GetExpireDateCompat14(subsidy_id).date(); }
AITown.FoundTownCompat14 <- AITown.FoundTown; AITown.FoundTownCompat14 <- AITown.FoundTown;
AITown.FoundTown <- function(tile, size, city, layout, name) { return AITown.FoundTownCompat14(tile, size, city, layout, AICompat14.Text(name)); } AITown.FoundTown <- function(tile, size, city, layout, name) { return AITown.FoundTownCompat14(tile, size, city, layout, AICompat14.Text(name)); }

View File

@ -7,6 +7,19 @@
/* This file contains code to downgrade the API from 15 to 14. */ /* This file contains code to downgrade the API from 15 to 14. */
GSDate <- GSEconomyDate;
GSDate.IsValidDate <- function(date) { return GSDate(date).IsValid(); }
GSDate.GetCurrentDateCompat14 <- GSDate.GetCurrentDate;
GSDate.GetCurrentDate <- function() { return GSDate.GetCurrentDateCompat14().date(); }
GSDate.GetYearCompat14 <- GSDate.GetYear;
GSDate.GetYear <- function(date) { return GSDate(date).GetYearCompat14(); }
GSDate.GetMonthCompat14 <- GSDate.GetMonth;
GSDate.GetMonth <- function(date) { return GSDate(date).GetMonthCompat14(); }
GSDate.GetDayOfMonthCompat14 <- GSDate.GetDayOfMonth;
GSDate.GetDayOfMonth <- function(date) { return GSDate(date).GetDayOfMonthCompat14(); }
GSDate.GetDateCompat14 <- GSDate.GetDate;
GSDate.GetDate <- function(year, month, day) { return GSDate.GetDateCompat14(year, month, day).date(); }
GSBridge.GetBridgeID <- GSBridge.GetBridgeType; GSBridge.GetBridgeID <- GSBridge.GetBridgeType;
/* Emulate old GSText parameter padding behaviour */ /* Emulate old GSText parameter padding behaviour */
@ -21,6 +34,8 @@ class GSCompat14 {
} }
} }
GSBaseStation.GetConstructionDateCompat14 <- GSBaseStation.GetConstructionDate;
GSBaseStation.GetConstructionDate <- function(station_id) { return GSBaseStation.GetConstructionDateCompat14(station_id).date(); }
GSBaseStation.SetNameCompat14 <- GSBaseStation.SetName; GSBaseStation.SetNameCompat14 <- GSBaseStation.SetName;
GSBaseStation.SetName <- function(id, name) { return GSBaseStation.SetNameCompat14(id, GSCompat14.Text(name)); } GSBaseStation.SetName <- function(id, name) { return GSBaseStation.SetNameCompat14(id, GSCompat14.Text(name)); }
@ -29,6 +44,9 @@ GSCompany.SetName <- function(name) { return GSCompany.SetNameCompat14(GSCompat1
GSCompany.SetPresidentNameCompat14 <- GSCompany.SetPresidentName; GSCompany.SetPresidentNameCompat14 <- GSCompany.SetPresidentName;
GSCompany.SetPresidentName <- function(name) { return GSCompany.SetPresidentNameCompat14(GSCompat14.Text(name)); } GSCompany.SetPresidentName <- function(name) { return GSCompany.SetPresidentNameCompat14(GSCompat14.Text(name)); }
GSEngine.GetDesignDateCompat14 <- GSEngine.GetDesignDate;
GSEngine.GetDesignDate <- function(engine_id) { return GSEngine.GetDesignDateCompat14(engine_id).date(); }
GSGoal.NewCompat14 <- GSGoal.New; GSGoal.NewCompat14 <- GSGoal.New;
GSGoal.New <- function(company, goal, type, dest) { return GSGoal.NewCompat14(company, GSCompat14.Text(goal), type, dest); } GSGoal.New <- function(company, goal, type, dest) { return GSGoal.NewCompat14(company, GSCompat14.Text(goal), type, dest); }
GSGoal.SetTextCompat14 <- GSGoal.SetText; GSGoal.SetTextCompat14 <- GSGoal.SetText;
@ -43,6 +61,10 @@ GSGoal.QuestionClient <- function(id, target, is_client, question, type, buttons
GSGroup.SetNameCompat14 <- GSGroup.SetName; GSGroup.SetNameCompat14 <- GSGroup.SetName;
GSGroup.SetName <- function(id, name) { return GSGroup.SetNameCompat14(id, GSCompat14.Text(name)); } GSGroup.SetName <- function(id, name) { return GSGroup.SetNameCompat14(id, GSCompat14.Text(name)); }
GSIndustry.GetConstructionDateCompat14 <- GSIndustry.GetConstructionDate;
GSIndustry.GetConstructionDate <- function(industry_id) { return GSIndustry.GetConstructionDateCompat14(industry_id).date(); }
GSIndustry.GetCargoLastAcceptedDateCompat14 <- GSIndustry.GetCargoLastAcceptedDate;
GSIndustry.GetCargoLastAcceptedDate <- function(industry_id, cargo_type) { return GSIndustry.GetCargoLastAcceptedDateCompat14(industry_id, cargo_type).date(); }
GSIndustry.SetTextCompat14 <- GSIndustry.SetText; GSIndustry.SetTextCompat14 <- GSIndustry.SetText;
GSIndustry.SetText <- function(id, text) { return GSIndustry.SetTextCompat14(id, GSCompat14.Text(text)); } GSIndustry.SetText <- function(id, text) { return GSIndustry.SetTextCompat14(id, GSCompat14.Text(text)); }
GSIndustry.SetProductionLevelCompat14 <- GSIndustry.SetProductionLevel; GSIndustry.SetProductionLevelCompat14 <- GSIndustry.SetProductionLevel;
@ -63,15 +85,22 @@ GSNews.Create <- function(type, text, company, ref_type, ref) { return GSNews.Cr
GSSign.BuildSignCompat14 <- GSSign.BuildSign; GSSign.BuildSignCompat14 <- GSSign.BuildSign;
GSSign.BuildSign <- function(id, name) { return GSSign.BuildSignCompat14(id, GSCompat14.Text(name)); } GSSign.BuildSign <- function(id, name) { return GSSign.BuildSignCompat14(id, GSCompat14.Text(name)); }
GSStoryPage.GetDateCompat14 <- GSStoryPage.GetDate;
GSStoryPage.GetDate <- function(story_page_id) { return GSStoryPage.GetDateCompat14(story_page_id).date(); }
GSStoryPage.NewCompat14 <- GSStoryPage.New; GSStoryPage.NewCompat14 <- GSStoryPage.New;
GSStoryPage.New <- function(company, title) { return GSStoryPage.NewCompat14(company, GSCompat14.Text(title)); } GSStoryPage.New <- function(company, title) { return GSStoryPage.NewCompat14(company, GSCompat14.Text(title)); }
GSStoryPage.NewElementCompat14 <- GSStoryPage.NewElement; GSStoryPage.NewElementCompat14 <- GSStoryPage.NewElement;
GSStoryPage.NewElement <- function(page, type, ref, text) { return GSStoryPage.NewElementCompat14(page, type, ref, GSCompat14.Text(text)); } GSStoryPage.NewElement <- function(page, type, ref, text) { return GSStoryPage.NewElementCompat14(page, type, ref, GSCompat14.Text(text)); }
GSStoryPage.UpdateElementCompat14 <- GSStoryPage.UpdateElement; GSStoryPage.UpdateElementCompat14 <- GSStoryPage.UpdateElement;
GSStoryPage.UpdateElement <- function(id, ref, text) { return GSStoryPage.UpdateElementCompat14(id, ref, GSCompat14.Text(text)); } GSStoryPage.UpdateElement <- function(id, ref, text) { return GSStoryPage.UpdateElementCompat14(id, ref, GSCompat14.Text(text)); }
GSStoryPage.SetDateCompat14 <- GSStoryPage.SetDate;
GSStoryPage.SetDate <- function(story_page_id, date) { return GSStoryPage.SetDateCompat14(story_page_id, GSCalendarDate(date)); }
GSStoryPage.SetTitleCompat14 <- GSStoryPage.SetTitle; GSStoryPage.SetTitleCompat14 <- GSStoryPage.SetTitle;
GSStoryPage.SetTitle <- function(page, tile) { return GSStoryPage.SetTitleCompat14(page, GSCompat14.Text(title)); } GSStoryPage.SetTitle <- function(page, tile) { return GSStoryPage.SetTitleCompat14(page, GSCompat14.Text(title)); }
GSSubsidy.GetExpireDateCompat14 <- GSSubsidy.GetExpireDate;
GSSubsidy.GetExpireDate <- function(subsidy_id) { return GSSubsidy.GetExpireDateCompat14(subsidy_id).date(); }
GSTown.SetNameCompat14 <- GSTown.SetName; GSTown.SetNameCompat14 <- GSTown.SetName;
GSTown.SetName <- function(id, name) { return GSTown.SetNameCompat14(id, GSCompat14.Text(name)); } GSTown.SetName <- function(id, name) { return GSTown.SetNameCompat14(id, GSCompat14.Text(name)); }
GSTown.SetTextCompat14 <- GSTown.SetText; GSTown.SetTextCompat14 <- GSTown.SetText;

View File

@ -103,14 +103,14 @@ void SpriteFontCache::ClearFontCache()
const Sprite *SpriteFontCache::GetGlyph(GlyphID key) const Sprite *SpriteFontCache::GetGlyph(GlyphID key)
{ {
SpriteID sprite = this->GetUnicodeGlyph(static_cast<char32_t>(key & ~SPRITE_GLYPH)); SpriteID sprite = static_cast<SpriteID>(key & ~SPRITE_GLYPH);
if (sprite == 0) sprite = this->GetUnicodeGlyph('?'); if (sprite == 0) sprite = this->GetUnicodeGlyph('?');
return GetSprite(sprite, SpriteType::Font); return GetSprite(sprite, SpriteType::Font);
} }
uint SpriteFontCache::GetGlyphWidth(GlyphID key) uint SpriteFontCache::GetGlyphWidth(GlyphID key)
{ {
SpriteID sprite = this->GetUnicodeGlyph(static_cast<char32_t>(key & ~SPRITE_GLYPH)); SpriteID sprite = static_cast<SpriteID>(key & ~SPRITE_GLYPH);
if (sprite == 0) sprite = this->GetUnicodeGlyph('?'); if (sprite == 0) sprite = this->GetUnicodeGlyph('?');
return SpriteExists(sprite) ? GetSprite(sprite, SpriteType::Font)->width + ScaleFontTrad(this->fs != FS_NORMAL ? 1 : 0) : 0; return SpriteExists(sprite) ? GetSprite(sprite, SpriteType::Font)->width + ScaleFontTrad(this->fs != FS_NORMAL ? 1 : 0) : 0;
} }
@ -120,7 +120,7 @@ GlyphID SpriteFontCache::MapCharToGlyph(char32_t key, [[maybe_unused]] bool allo
assert(IsPrintable(key)); assert(IsPrintable(key));
SpriteID sprite = this->GetUnicodeGlyph(key); SpriteID sprite = this->GetUnicodeGlyph(key);
if (sprite == 0) return 0; if (sprite == 0) return 0;
return SPRITE_GLYPH | key; return SPRITE_GLYPH | sprite;
} }
bool SpriteFontCache::GetDrawGlyphShadow() bool SpriteFontCache::GetDrawGlyphShadow()

View File

@ -105,8 +105,8 @@ static ChangeInfoResult RoadStopChangeInfo(uint first, uint last, int prop, Byte
AddStringForMapping(GRFStringID{buf.ReadWord()}, [rs = rs.get()](StringID str) { RoadStopClass::Get(rs->class_index)->name = str; }); AddStringForMapping(GRFStringID{buf.ReadWord()}, [rs = rs.get()](StringID str) { RoadStopClass::Get(rs->class_index)->name = str; });
break; break;
case 0x0C: // The draw mode case 0x0C: // The draw modes
rs->draw_mode = static_cast<RoadStopDrawMode>(buf.ReadByte()); rs->draw_mode = static_cast<RoadStopDrawModes>(buf.ReadByte());
break; break;
case 0x0D: // Cargo types for random triggers case 0x0D: // Cargo types for random triggers

View File

@ -298,7 +298,7 @@ void DrawRoadStopTile(int x, int y, RoadType roadtype, const RoadStopSpec *spec,
RoadStopDrawModes draw_mode; RoadStopDrawModes draw_mode;
if (spec->flags.Test(RoadStopSpecFlag::DrawModeRegister)) { if (spec->flags.Test(RoadStopSpecFlag::DrawModeRegister)) {
draw_mode = static_cast<RoadStopDrawMode>(object.GetRegister(0x100)); draw_mode = static_cast<RoadStopDrawModes>(object.GetRegister(0x100));
} else { } else {
draw_mode = spec->draw_mode; draw_mode = spec->draw_mode;
} }

View File

@ -40,13 +40,15 @@ foreach(API "ai;AI" "game;GS" "template;Template")
list(GET API 1 APIUC) list(GET API 1 APIUC)
foreach(SCRIPT_API_FILE IN LISTS SCRIPT_API_FILES) foreach(SCRIPT_API_FILE IN LISTS SCRIPT_API_FILES)
if("${SCRIPT_API_FILE}" MATCHES ".*script_controller.*")
continue()
endif()
get_filename_component(SCRIPT_API_FILE_NAME "${SCRIPT_API_FILE}" NAME_WE) get_filename_component(SCRIPT_API_FILE_NAME "${SCRIPT_API_FILE}" NAME_WE)
string(REPLACE "script_" "${APILC}_" SCRIPT_API_FILE_NAME "${SCRIPT_API_FILE_NAME}") string(REPLACE "script_" "${APILC}_" SCRIPT_API_FILE_NAME "${SCRIPT_API_FILE_NAME}")
set(SCRIPT_API_BINARY_FILE "${CMAKE_BINARY_DIR}/generated/script/api/${APILC}/${SCRIPT_API_FILE_NAME}.sq.hpp") set(SCRIPT_API_BINARY_FILE "${CMAKE_BINARY_DIR}/generated/script/api/${APILC}/${SCRIPT_API_FILE_NAME}.sq.hpp")
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${APILC}/${SCRIPT_API_FILE_NAME}.sq.hpp")
file(REMOVE "${SCRIPT_API_BINARY_FILE}")
continue()
endif()
add_custom_command_timestamp(OUTPUT ${SCRIPT_API_BINARY_FILE} add_custom_command_timestamp(OUTPUT ${SCRIPT_API_BINARY_FILE}
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
-DSCRIPT_API_SOURCE_FILE=${CMAKE_CURRENT_SOURCE_DIR}/squirrel_export.sq.hpp.in -DSCRIPT_API_SOURCE_FILE=${CMAKE_CURRENT_SOURCE_DIR}/squirrel_export.sq.hpp.in
@ -74,6 +76,7 @@ foreach(API "ai;AI" "game;GS" "template;Template")
if(NOT "${APILC}" STREQUAL "template") if(NOT "${APILC}" STREQUAL "template")
list(APPEND SCRIPT_${APIUC}_BINARY_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${APILC}/${APILC}_controller.sq.hpp") list(APPEND SCRIPT_${APIUC}_BINARY_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${APILC}/${APILC}_controller.sq.hpp")
list(APPEND SCRIPT_${APIUC}_BINARY_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${APILC}/${APILC}_date.sq.hpp")
set(INCLUDES_BINARY_FILE "${CMAKE_BINARY_DIR}/generated/script/api/${APILC}/${APILC}_includes.hpp") set(INCLUDES_BINARY_FILE "${CMAKE_BINARY_DIR}/generated/script/api/${APILC}/${APILC}_includes.hpp")
set(API_FILES "${CMAKE_CURRENT_BINARY_DIR}/${APILC}.files") set(API_FILES "${CMAKE_CURRENT_BINARY_DIR}/${APILC}.files")
file(GENERATE OUTPUT ${API_FILES} CONTENT "${SCRIPT_${APIUC}_BINARY_FILES}") file(GENERATE OUTPUT ${API_FILES} CONTENT "${SCRIPT_${APIUC}_BINARY_FILES}")
@ -120,6 +123,7 @@ foreach(API "ai;AI" "game;GS" "template;Template")
) )
endif() endif()
else() else()
list(APPEND SCRIPT_Template_BINARY_FILES "${CMAKE_CURRENT_SOURCE_DIR}/template/template_date.sq.hpp")
add_dependencies(script_api add_dependencies(script_api
script_${APILC} script_${APILC}
) )
@ -233,7 +237,6 @@ add_files(
script_company.cpp script_company.cpp
script_companymode.cpp script_companymode.cpp
script_controller.cpp script_controller.cpp
script_date.cpp
script_depotlist.cpp script_depotlist.cpp
script_engine.cpp script_engine.cpp
script_enginelist.cpp script_enginelist.cpp

View File

@ -0,0 +1,62 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../script_date.hpp"
#include "../template/template_date.sq.hpp"
template <> SQInteger PushClassName<ScriptEconomyDate, ScriptType::AI>(HSQUIRRELVM vm) { sq_pushstring(vm, "AIEconomyDate"); return 1; }
template <> SQInteger PushClassName<ScriptCalendarDate, ScriptType::AI>(HSQUIRRELVM vm) { sq_pushstring(vm, "AICalendarDate"); return 1; }
void SQAIDate_Register(Squirrel &engine)
{
DefSQClass<ScriptEconomyDate, ScriptType::AI> SQAIEconomyDate("AIEconomyDate");
SQAIEconomyDate.PreRegister(engine, "AIObject");
SQAIEconomyDate.AddSQAdvancedConstructor(engine);
SQAIEconomyDate.DefSQConst(engine, ScriptEconomyDate::DATE_INVALID, "DATE_INVALID");
SQAIEconomyDate.DefSQStaticMethod(engine, &ScriptEconomyDate::GetCurrentDate, "GetCurrentDate", ".");
SQAIEconomyDate.DefSQStaticMethod(engine, &ScriptEconomyDate::GetDate, "GetDate", ".iii");
SQAIEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::IsValid, "IsValid", ".");
SQAIEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::GetYear, "GetYear", ".");
SQAIEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::GetMonth, "GetMonth", ".");
SQAIEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::GetDayOfMonth, "GetDayOfMonth", ".");
SQAIEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::date, "date", ".");
SQAIEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_tostring, "_tostring");
SQAIEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_add, "_add");
SQAIEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_sub, "_sub");
SQAIEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_cmp, "_cmp");
SQAIEconomyDate.PostRegister(engine);
DefSQClass<ScriptCalendarDate, ScriptType::AI> SQAICalendarDate("AICalendarDate");
SQAICalendarDate.PreRegister(engine, "AIObject");
SQAICalendarDate.AddSQAdvancedConstructor(engine);
SQAICalendarDate.DefSQConst(engine, ScriptCalendarDate::DATE_INVALID, "DATE_INVALID");
SQAICalendarDate.DefSQStaticMethod(engine, &ScriptCalendarDate::GetCurrentDate, "GetCurrentDate", ".");
SQAICalendarDate.DefSQStaticMethod(engine, &ScriptCalendarDate::GetDate, "GetDate", ".iii");
SQAICalendarDate.DefSQMethod(engine, &ScriptCalendarDate::IsValid, "IsValid", ".");
SQAICalendarDate.DefSQMethod(engine, &ScriptCalendarDate::GetYear, "GetYear", ".");
SQAICalendarDate.DefSQMethod(engine, &ScriptCalendarDate::GetMonth, "GetMonth", ".");
SQAICalendarDate.DefSQMethod(engine, &ScriptCalendarDate::GetDayOfMonth, "GetDayOfMonth", ".");
SQAICalendarDate.DefSQMethod(engine, &ScriptCalendarDate::date, "date", ".");
SQAICalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_tostring, "_tostring");
SQAICalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_add, "_add");
SQAICalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_sub, "_sub");
SQAICalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_cmp, "_cmp");
SQAICalendarDate.PostRegister(engine);
}

View File

@ -28,6 +28,11 @@
* \li AICargo::CC_POTABLE * \li AICargo::CC_POTABLE
* \li AICargo::CC_NON_POTABLE * \li AICargo::CC_NON_POTABLE
* \li AIVehicleList_Waypoint * \li AIVehicleList_Waypoint
* \li AIEconomyDate
* \li AICalendarDate
*
* API removals:
* \li AIDate
* *
* Other changes: * Other changes:
* \li AIBridge::GetBridgeID renamed to AIBridge::GetBridgeType * \li AIBridge::GetBridgeID renamed to AIBridge::GetBridgeType

View File

@ -0,0 +1,62 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../script_date.hpp"
#include "../template/template_date.sq.hpp"
template <> SQInteger PushClassName<ScriptEconomyDate, ScriptType::GS>(HSQUIRRELVM vm) { sq_pushstring(vm, "GSEconomyDate"); return 1; }
template <> SQInteger PushClassName<ScriptCalendarDate, ScriptType::GS>(HSQUIRRELVM vm) { sq_pushstring(vm, "GSCalendarDate"); return 1; }
void SQGSDate_Register(Squirrel &engine)
{
DefSQClass<ScriptEconomyDate, ScriptType::GS> SQGSEconomyDate("GSEconomyDate");
SQGSEconomyDate.PreRegister(engine, "GSObject");
SQGSEconomyDate.AddSQAdvancedConstructor(engine);
SQGSEconomyDate.DefSQConst(engine, ScriptEconomyDate::DATE_INVALID, "DATE_INVALID");
SQGSEconomyDate.DefSQStaticMethod(engine, &ScriptEconomyDate::GetCurrentDate, "GetCurrentDate", ".");
SQGSEconomyDate.DefSQStaticMethod(engine, &ScriptEconomyDate::GetDate, "GetDate", ".iii");
SQGSEconomyDate.DefSQStaticMethod(engine, &ScriptEconomyDate::GetSystemTime, "GetSystemTime", ".");
SQGSEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::IsValid, "IsValid", ".");
SQGSEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::GetYear, "GetYear", ".");
SQGSEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::GetMonth, "GetMonth", ".");
SQGSEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::GetDayOfMonth, "GetDayOfMonth", ".");
SQGSEconomyDate.DefSQMethod(engine, &ScriptEconomyDate::date, "date", ".");
SQGSEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_tostring, "_tostring");
SQGSEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_add, "_add");
SQGSEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_sub, "_sub");
SQGSEconomyDate.DefSQAdvancedMethod(engine, &ScriptEconomyDate::_cmp, "_cmp");
SQGSEconomyDate.PostRegister(engine);
DefSQClass<ScriptCalendarDate, ScriptType::GS> SQGSCalendarDate("GSCalendarDate");
SQGSCalendarDate.PreRegister(engine, "GSObject");
SQGSCalendarDate.AddSQAdvancedConstructor(engine);
SQGSCalendarDate.DefSQConst(engine, ScriptCalendarDate::DATE_INVALID, "DATE_INVALID");
SQGSCalendarDate.DefSQStaticMethod(engine, &ScriptCalendarDate::GetCurrentDate, "GetCurrentDate", ".");
SQGSCalendarDate.DefSQStaticMethod(engine, &ScriptCalendarDate::GetDate, "GetDate", ".iii");
SQGSCalendarDate.DefSQStaticMethod(engine, &ScriptCalendarDate::GetSystemTime, "GetSystemTime", ".");
SQGSCalendarDate.DefSQMethod(engine, &ScriptCalendarDate::IsValid, "IsValid", ".");
SQGSCalendarDate.DefSQMethod(engine, &ScriptCalendarDate::GetYear, "GetYear", ".");
SQGSCalendarDate.DefSQMethod(engine, &ScriptCalendarDate::GetMonth, "GetMonth", ".");
SQGSCalendarDate.DefSQMethod(engine, &ScriptCalendarDate::GetDayOfMonth, "GetDayOfMonth", ".");
SQGSCalendarDate.DefSQMethod(engine, &ScriptCalendarDate::date, "date", ".");
SQGSCalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_tostring, "_tostring");
SQGSCalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_add, "_add");
SQGSCalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_sub, "_sub");
SQGSCalendarDate.DefSQAdvancedMethod(engine, &ScriptCalendarDate::_cmp, "_cmp");
SQGSCalendarDate.PostRegister(engine);
}

View File

@ -29,6 +29,11 @@
* \li GSCargo::CC_NON_POTABLE * \li GSCargo::CC_NON_POTABLE
* \li GSVehicleList_Waypoint * \li GSVehicleList_Waypoint
* \li GSBaseStation::GetOwner * \li GSBaseStation::GetOwner
* \li GSEconomyDate
* \li GSCalendarDate
*
* API removals:
* \li GSDate
* *
* Other changes: * Other changes:
* \li GSBridge::GetBridgeID renamed to GSBridge::GetBridgeType * \li GSBridge::GetBridgeID renamed to GSBridge::GetBridgeType

View File

@ -66,9 +66,9 @@
return ::BaseStation::Get(station_id)->xy; return ::BaseStation::Get(station_id)->xy;
} }
/* static */ ScriptDate::Date ScriptBaseStation::GetConstructionDate(StationID station_id) /* static */ ScriptCalendarDate *ScriptBaseStation::GetConstructionDate(StationID station_id)
{ {
if (!IsValidBaseStation(station_id)) return ScriptDate::DATE_INVALID; if (!IsValidBaseStation(station_id)) return new ScriptCalendarDate();
return (ScriptDate::Date)::BaseStation::Get(station_id)->build_date.base(); return new ScriptCalendarDate(static_cast<ScriptCalendarDate::Date>(::BaseStation::Get(station_id)->build_date.base()));
} }

View File

@ -78,7 +78,7 @@ public:
* @return The last calendar-date some part of this station was build. * @return The last calendar-date some part of this station was build.
* @see \ref ScriptCalendarTime * @see \ref ScriptCalendarTime
*/ */
static ScriptDate::Date GetConstructionDate(StationID station_id); static ScriptCalendarDate *GetConstructionDate(StationID station_id);
}; };
#endif /* SCRIPT_BASESTATION_HPP */ #endif /* SCRIPT_BASESTATION_HPP */

View File

@ -46,9 +46,9 @@ static NetworkClientInfo *FindClientInfo(ScriptClient::ClientID client)
return ScriptCompany::ToScriptCompanyID(ci->client_playas); return ScriptCompany::ToScriptCompanyID(ci->client_playas);
} }
/* static */ ScriptDate::Date ScriptClient::GetJoinDate(ScriptClient::ClientID client) /* static */ ScriptEconomyDate *ScriptClient::GetJoinDate(ScriptClient::ClientID client)
{ {
NetworkClientInfo *ci = FindClientInfo(client); NetworkClientInfo *ci = FindClientInfo(client);
if (ci == nullptr) return ScriptDate::DATE_INVALID; if (ci == nullptr) return new ScriptEconomyDate();
return (ScriptDate::Date)ci->join_date.base(); return new ScriptEconomyDate(static_cast<ScriptEconomyDate::Date>(ci->join_date.base()));
} }

View File

@ -62,7 +62,7 @@ public:
* @return The economy-date when client has joined. * @return The economy-date when client has joined.
* @see \ref ScriptEconomyTime * @see \ref ScriptEconomyTime
*/ */
static ScriptDate::Date GetJoinDate(ClientID client); static ScriptEconomyDate *GetJoinDate(ClientID client);
}; };

View File

@ -76,7 +76,7 @@ ScriptController::ScriptController(::CompanyID company) :
/* static */ uint ScriptController::GetTick() /* static */ uint ScriptController::GetTick()
{ {
return ScriptObject::GetActiveInstance().GetController()->ticks; return ScriptObject::GetActiveInstance().GetController().ticks;
} }
/* static */ int ScriptController::GetOpsTillSuspend() /* static */ int ScriptController::GetOpsTillSuspend()
@ -96,9 +96,9 @@ ScriptController::ScriptController(::CompanyID company) :
/* static */ HSQOBJECT ScriptController::Import(const std::string &library, const std::string &class_name, int version) /* static */ HSQOBJECT ScriptController::Import(const std::string &library, const std::string &class_name, int version)
{ {
ScriptController *controller = ScriptObject::GetActiveInstance().GetController(); ScriptController &controller = ScriptObject::GetActiveInstance().GetController();
Squirrel *engine = ScriptObject::GetActiveInstance().engine; Squirrel &engine = *ScriptObject::GetActiveInstance().engine;
HSQUIRRELVM vm = engine->GetVM(); HSQUIRRELVM vm = engine.GetVM();
ScriptInfo *lib = ScriptObject::GetActiveInstance().FindLibrary(library, version); ScriptInfo *lib = ScriptObject::GetActiveInstance().FindLibrary(library, version);
if (lib == nullptr) { if (lib == nullptr) {
@ -114,11 +114,11 @@ ScriptController::ScriptController(::CompanyID company) :
std::string fake_class; std::string fake_class;
LoadedLibraryList::iterator it = controller->loaded_library.find(library_name); LoadedLibraryList::iterator it = controller.loaded_library.find(library_name);
if (it != controller->loaded_library.end()) { if (it != controller.loaded_library.end()) {
fake_class = (*it).second; fake_class = (*it).second;
} else { } else {
int next_number = ++controller->loaded_library_count; int next_number = ++controller.loaded_library_count;
/* Create a new fake internal name */ /* Create a new fake internal name */
fake_class = fmt::format("_internalNA{}", next_number); fake_class = fmt::format("_internalNA{}", next_number);
@ -128,14 +128,14 @@ ScriptController::ScriptController(::CompanyID company) :
sq_pushstring(vm, fake_class); sq_pushstring(vm, fake_class);
sq_newclass(vm, SQFalse); sq_newclass(vm, SQFalse);
/* Load the library */ /* Load the library */
if (!engine->LoadScript(vm, lib->GetMainScript(), false)) { if (!engine.LoadScript(vm, lib->GetMainScript(), false)) {
throw sq_throwerror(vm, fmt::format("there was a compile error when importing '{}' version {}", library, version)); throw sq_throwerror(vm, fmt::format("there was a compile error when importing '{}' version {}", library, version));
} }
/* Create the fake class */ /* Create the fake class */
sq_newslot(vm, -3, SQFalse); sq_newslot(vm, -3, SQFalse);
sq_pop(vm, 1); sq_pop(vm, 1);
controller->loaded_library[library_name] = fake_class; controller.loaded_library[library_name] = fake_class;
} }
/* Find the real class inside the fake class (like 'sets.Vector') */ /* Find the real class inside the fake class (like 'sets.Vector') */

View File

@ -1,68 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file script_date.cpp Implementation of ScriptDate. */
#include "../../stdafx.h"
#include "script_date.hpp"
#include "../../timer/timer_game_economy.h"
#include <time.h>
#include "../../safeguards.h"
/* static */ bool ScriptDate::IsValidDate(Date date)
{
return date >= 0;
}
/* static */ ScriptDate::Date ScriptDate::GetCurrentDate()
{
return (ScriptDate::Date)TimerGameEconomy::date.base();
}
/* static */ SQInteger ScriptDate::GetYear(ScriptDate::Date date)
{
if (date < 0) return DATE_INVALID;
::TimerGameEconomy::YearMonthDay ymd = ::TimerGameEconomy::ConvertDateToYMD(::TimerGameEconomy::Date{date});
return ymd.year.base();
}
/* static */ SQInteger ScriptDate::GetMonth(ScriptDate::Date date)
{
if (date < 0) return DATE_INVALID;
::TimerGameEconomy::YearMonthDay ymd = ::TimerGameEconomy::ConvertDateToYMD(::TimerGameEconomy::Date{date});
return ymd.month + 1;
}
/* static */ SQInteger ScriptDate::GetDayOfMonth(ScriptDate::Date date)
{
if (date < 0) return DATE_INVALID;
::TimerGameEconomy::YearMonthDay ymd = ::TimerGameEconomy::ConvertDateToYMD(::TimerGameEconomy::Date{date});
return ymd.day;
}
/* static */ ScriptDate::Date ScriptDate::GetDate(SQInteger year, SQInteger month, SQInteger day_of_month)
{
if (month < 1 || month > 12) return DATE_INVALID;
if (day_of_month < 1 || day_of_month > 31) return DATE_INVALID;
::TimerGameEconomy::Year timer_year{ClampTo<int32_t>(year)};
if (timer_year < EconomyTime::MIN_YEAR || timer_year > EconomyTime::MAX_YEAR) return DATE_INVALID;
return static_cast<ScriptDate::Date>(::TimerGameEconomy::ConvertYMDToDate(timer_year, month - 1, day_of_month).base());
}
/* static */ SQInteger ScriptDate::GetSystemTime()
{
time_t t;
time(&t);
return t;
}

View File

@ -12,7 +12,175 @@
#include "script_object.hpp" #include "script_object.hpp"
#include "../../timer/timer_game_economy.h" #include "../../timer/timer_game_economy.h"
#include "../squirrel_helper.hpp"
#ifndef DOXYGEN_API
template <size_t N>
struct StringLiteral {
constexpr StringLiteral(const char (&str)[N])
{
std::copy_n(str, N, this->value);
}
char value[N];
};
template <class Timer, class Time, StringLiteral Tag>
class ScriptDateBase : public ScriptObject {
public:
using YearMonthDay = Timer::YearMonthDay;
using Year = Timer::Year;
enum Date {
DATE_INVALID = Time::INVALID_DATE.base(),
};
ScriptDateBase(Date date = DATE_INVALID) : _date(date) {}
ScriptDateBase(HSQUIRRELVM vm) : _date(DATE_INVALID)
{
int nparam = sq_gettop(vm) - 1;
if (nparam >= 1) {
SQInteger date;
if (SQ_FAILED(sq_getinteger(vm, 2, &date))) {
throw sq_throwerror(vm, "Argument must be an integer");
}
this->_date = static_cast<Date>(date);
}
}
bool IsValid()
{
return this->_date > 0;
}
static ScriptDateBase *GetCurrentDate()
{
return new ScriptDateBase(static_cast<Date>(Timer::date.base()));
}
SQInteger GetYear()
{
if (!this->IsValid()) return DATE_INVALID;
YearMonthDay ymd = Timer::ConvertDateToYMD(static_cast<Timer::Date>(this->_date));
return ymd.year.base();
}
SQInteger GetMonth()
{
if (!this->IsValid()) return DATE_INVALID;
YearMonthDay ymd = Timer::ConvertDateToYMD(static_cast<Timer::Date>(this->_date));
return ymd.month + 1;
}
SQInteger GetDayOfMonth()
{
if (!this->IsValid()) return DATE_INVALID;
YearMonthDay ymd = Timer::ConvertDateToYMD(static_cast<Timer::Date>(this->_date));
return ymd.day;
}
static ScriptDateBase *GetDate(SQInteger year, SQInteger month, SQInteger day_of_month)
{
if (month < 1 || month > 12) return new ScriptDateBase();
if (day_of_month < 1 || day_of_month > 31) return new ScriptDateBase();
Year timer_year{ClampTo<int32_t>(year)};
if (timer_year < Time::MIN_YEAR || timer_year > Time::MAX_YEAR) return new ScriptDateBase();
return new ScriptDateBase(static_cast<Date>(Timer::ConvertYMDToDate(timer_year, month - 1, day_of_month).base()));
}
static SQInteger GetSystemTime()
{
time_t t;
time(&t);
return t;
}
Date date() { return this->_date; }
SQInteger _tostring(HSQUIRRELVM vm)
{
sq_pushstring(vm, fmt::format("{}", this->_date));
return 1;
}
SQInteger _add(HSQUIRRELVM vm)
{
SQInteger days = 0;
switch (sq_gettype(vm, 2)) {
case OT_INTEGER:
sq_getinteger(vm, 2, &days);
break;
case OT_INSTANCE: {
ScriptDateBase *other = static_cast<ScriptDateBase *>(Squirrel::GetRealInstance(vm, 2, Tag.value));
if (other == nullptr) return SQ_ERROR;
days = other->_date;
break;
}
default: return SQ_ERROR;
}
ScriptDateBase *res = new ScriptDateBase(static_cast<Date>(this->_date + days));
res->AddRef();
Squirrel::CreateClassInstanceVM(vm, Tag.value, res, nullptr, SQConvert::DefSQDestructorCallback<ScriptDateBase>, true);
return 1;
}
SQInteger _sub(HSQUIRRELVM vm)
{
SQInteger days = 0;
switch (sq_gettype(vm, 2)) {
case OT_INTEGER:
sq_getinteger(vm, 2, &days);
break;
case OT_INSTANCE: {
ScriptDateBase *other = static_cast<ScriptDateBase *>(Squirrel::GetRealInstance(vm, 2, Tag.value));
if (other == nullptr) return SQ_ERROR;
days = other->_date;
break;
}
default: return SQ_ERROR;
}
ScriptDateBase *res = new ScriptDateBase(static_cast<Date>(this->_date - days));
res->AddRef();
Squirrel::CreateClassInstanceVM(vm, Tag.value, res, nullptr, SQConvert::DefSQDestructorCallback<ScriptDateBase>, true);
return 1;
}
SQInteger _cmp(HSQUIRRELVM vm)
{
ScriptDateBase *other = static_cast<ScriptDateBase *>(Squirrel::GetRealInstance(vm, 2, Tag.value));
if (other == nullptr) return SQ_ERROR;
sq_pushinteger(vm, this->_date - other->_date);
return 1;
}
bool SaveObject(HSQUIRRELVM vm) override
{
sq_pushstring(vm, Tag.value);
sq_pushinteger(vm, this->_date);
return true;
}
bool LoadObject(HSQUIRRELVM vm) override
{
if (sq_gettype(vm, -1) != OT_INTEGER) return false;
SQInteger val;
sq_getinteger(vm, -1, &val);
this->_date = static_cast<Date>(val);
return true;
}
protected:
Date _date = DATE_INVALID;
};
using ScriptEconomyDate = ScriptDateBase<TimerGameEconomy, EconomyTime, "EconomyDate">;
using ScriptCalendarDate = ScriptDateBase<TimerGameCalendar, CalendarTime, "CalendarDate">;
#else
/** /**
* Class that handles all date related (calculation) functions. * Class that handles all date related (calculation) functions.
* @api ai game * @api ai game
@ -48,22 +216,23 @@
* Economy-time will use a 360 day calendar (12 months with 30 days each), which runs at a constant speed of one economy-month per realtime-minute. * Economy-time will use a 360 day calendar (12 months with 30 days each), which runs at a constant speed of one economy-month per realtime-minute.
* Calendar-time will use a Gregorian calendar, which can be slowed to stopped via game settings. * Calendar-time will use a Gregorian calendar, which can be slowed to stopped via game settings.
*/ */
class ScriptDate : public ScriptObject { class ScriptEconomyDate : public ScriptObject {
public: public:
/** /**
* Date data type is an integer value. Use ScriptDate::GetDate to * Date data type is an integer value. Use ScriptEconomyDate::GetDate to
* compose valid date values for a known year, month and day. * compose valid date values for a known year, month and day.
*/ */
enum Date { enum Date {
DATE_INVALID = ::EconomyTime::INVALID_DATE.base(), ///< A value representing an invalid date. DATE_INVALID, ///< A value representing an invalid date.
}; };
ScriptEconomyDate(Date date = DATE_INVALID);
/** /**
* Validates if a date value represent a valid date. * Validates if a date value represent a valid date.
* @param date The date to validate.
* @return True if the date is valid, otherwise false * @return True if the date is valid, otherwise false
*/ */
static bool IsValidDate(Date date); bool IsValid();
/** /**
* Get the current date. * Get the current date.
@ -72,28 +241,25 @@ public:
* 100 but not by 400. * 100 but not by 400.
* @return The current date. * @return The current date.
*/ */
static Date GetCurrentDate(); static ScriptEconomyDate GetCurrentDate();
/** /**
* Get the year of the given date. * Get the year of the given date.
* @param date The date to get the year of.
* @return The year. * @return The year.
*/ */
static SQInteger GetYear(Date date); SQInteger GetYear();
/** /**
* Get the month of the given date. * Get the month of the given date.
* @param date The date to get the month of.
* @return The month. * @return The month.
*/ */
static SQInteger GetMonth(Date date); SQInteger GetMonth();
/** /**
* Get the day (of the month) of the given date. * Get the day (of the month) of the given date.
* @param date The date to get the day of.
* @return The day. * @return The day.
*/ */
static SQInteger GetDayOfMonth(Date date); SQInteger GetDayOfMonth();
/** /**
* Get the date given a year, month and day of month. * Get the date given a year, month and day of month.
@ -102,7 +268,7 @@ public:
* @param day_of_month The day of month of the to-be determined date. * @param day_of_month The day of month of the to-be determined date.
* @return The date. * @return The date.
*/ */
static Date GetDate(SQInteger year, SQInteger month, SQInteger day_of_month); static ScriptEconomyDate GetDate(SQInteger year, SQInteger month, SQInteger day_of_month);
/** /**
* Get the time of the host system. * Get the time of the host system.
@ -111,6 +277,84 @@ public:
* @note This uses the clock of the host system, which can skew or be set back. Use with caution. * @note This uses the clock of the host system, which can skew or be set back. Use with caution.
*/ */
static SQInteger GetSystemTime(); static SQInteger GetSystemTime();
/**
* Get the date.
* @return The date.
*/
Date date();
}; };
class ScriptCalendarDate : public ScriptObject {
public:
/**
* Date data type is an integer value. Use ScriptCalendarDate::GetDate to
* compose valid date values for a known year, month and day.
*/
enum Date {
DATE_INVALID, ///< A value representing an invalid date.
};
ScriptCalendarDate(Date date = DATE_INVALID);
/**
* Validates if a date value represent a valid date.
* @return True if the date is valid, otherwise false
*/
bool IsValid();
/**
* Get the current date.
* This is the number of days since epoch under the assumption that
* there is a leap year every 4 years, except when dividable by
* 100 but not by 400.
* @return The current date.
*/
static ScriptCalendarDate GetCurrentDate();
/**
* Get the year of the given date.
* @return The year.
*/
SQInteger GetYear();
/**
* Get the month of the given date.
* @return The month.
*/
SQInteger GetMonth();
/**
* Get the day (of the month) of the given date.
* @return The day.
*/
SQInteger GetDayOfMonth();
/**
* Get the date given a year, month and day of month.
* @param year The year of the to-be determined date.
* @param month The month of the to-be determined date.
* @param day_of_month The day of month of the to-be determined date.
* @return The date.
*/
static ScriptCalendarDate GetDate(SQInteger year, SQInteger month, SQInteger day_of_month);
/**
* Get the time of the host system.
* @return The amount of seconds passed since 1 Jan 1970.
* @api -ai
* @note This uses the clock of the host system, which can skew or be set back. Use with caution.
*/
static SQInteger GetSystemTime();
/**
* Get the date.
* @return The date.
*/
Date date();
};
#endif /* DOXYGEN_API */
#endif /* SCRIPT_DATE_HPP */ #endif /* SCRIPT_DATE_HPP */

View File

@ -169,11 +169,11 @@
return ::Engine::Get(engine_id)->GetDisplayMaxTractiveEffort() / 1000; return ::Engine::Get(engine_id)->GetDisplayMaxTractiveEffort() / 1000;
} }
/* static */ ScriptDate::Date ScriptEngine::GetDesignDate(EngineID engine_id) /* static */ ScriptCalendarDate *ScriptEngine::GetDesignDate(EngineID engine_id)
{ {
if (!IsValidEngine(engine_id)) return ScriptDate::DATE_INVALID; if (!IsValidEngine(engine_id)) return new ScriptCalendarDate();
return (ScriptDate::Date)::Engine::Get(engine_id)->intro_date.base(); return new ScriptCalendarDate(static_cast<ScriptCalendarDate::Date>(::Engine::Get(engine_id)->intro_date.base()));
} }
/* static */ ScriptVehicle::VehicleType ScriptEngine::GetVehicleType(EngineID engine_id) /* static */ ScriptVehicle::VehicleType ScriptEngine::GetVehicleType(EngineID engine_id)

View File

@ -173,7 +173,7 @@ public:
* @return The calendar-date this engine was designed. * @return The calendar-date this engine was designed.
* @see \ref ScriptCalendarTime * @see \ref ScriptCalendarTime
*/ */
static ScriptDate::Date GetDesignDate(EngineID engine_id); static ScriptCalendarDate *GetDesignDate(EngineID engine_id);
/** /**
* Get the type of an engine. * Get the type of an engine.

View File

@ -49,11 +49,11 @@
return ::StrMakeValid(::GetString(STR_INDUSTRY_NAME, industry_id), {}); return ::StrMakeValid(::GetString(STR_INDUSTRY_NAME, industry_id), {});
} }
/* static */ ScriptDate::Date ScriptIndustry::GetConstructionDate(IndustryID industry_id) /* static */ ScriptCalendarDate *ScriptIndustry::GetConstructionDate(IndustryID industry_id)
{ {
const Industry *i = Industry::GetIfValid(industry_id); const Industry *i = Industry::GetIfValid(industry_id);
if (i == nullptr) return ScriptDate::DATE_INVALID; if (i == nullptr) return new ScriptCalendarDate();
return (ScriptDate::Date)i->construction_date.base(); return new ScriptCalendarDate(static_cast<ScriptCalendarDate::Date>(i->construction_date.base()));
} }
/* static */ bool ScriptIndustry::SetText(IndustryID industry_id, Text *text) /* static */ bool ScriptIndustry::SetText(IndustryID industry_id, Text *text)
@ -226,18 +226,18 @@
return i->last_prod_year.base(); return i->last_prod_year.base();
} }
/* static */ ScriptDate::Date ScriptIndustry::GetCargoLastAcceptedDate(IndustryID industry_id, CargoType cargo_type) /* static */ ScriptEconomyDate *ScriptIndustry::GetCargoLastAcceptedDate(IndustryID industry_id, CargoType cargo_type)
{ {
const Industry *i = Industry::GetIfValid(industry_id); const Industry *i = Industry::GetIfValid(industry_id);
if (i == nullptr) return ScriptDate::DATE_INVALID; if (i == nullptr) return new ScriptEconomyDate();
if (!::IsValidCargoType(cargo_type)) { if (!::IsValidCargoType(cargo_type)) {
auto it = std::max_element(std::begin(i->accepted), std::end(i->accepted), [](const auto &a, const auto &b) { return a.last_accepted < b.last_accepted; }); auto it = std::max_element(std::begin(i->accepted), std::end(i->accepted), [](const auto &a, const auto &b) { return a.last_accepted < b.last_accepted; });
return (ScriptDate::Date)it->last_accepted.base(); return new ScriptEconomyDate(static_cast<ScriptEconomyDate::Date>(it->last_accepted.base()));
} else { } else {
auto it = i->GetCargoAccepted(cargo_type); auto it = i->GetCargoAccepted(cargo_type);
if (it == std::end(i->accepted)) return ScriptDate::DATE_INVALID; if (it == std::end(i->accepted)) return new ScriptEconomyDate();
return (ScriptDate::Date)it->last_accepted.base(); return new ScriptEconomyDate(static_cast<ScriptEconomyDate::Date>(it->last_accepted.base()));
} }
} }

View File

@ -93,7 +93,7 @@ public:
* @see \ref ScriptCalendarTime * @see \ref ScriptCalendarTime
* @api -ai * @api -ai
*/ */
static ScriptDate::Date GetConstructionDate(IndustryID industry_id); static ScriptCalendarDate *GetConstructionDate(IndustryID industry_id);
/** /**
* Set the custom text of an industry, shown in the GUI. * Set the custom text of an industry, shown in the GUI.
@ -265,11 +265,11 @@ public:
* @param cargo_type The cargo to query, or INVALID_CARGO to query latest of all accepted cargoes. * @param cargo_type The cargo to query, or INVALID_CARGO to query latest of all accepted cargoes.
* @pre IsValidIndustry(industry_id). * @pre IsValidIndustry(industry_id).
* @pre IsValidCargo(cargo_type) || cargo_type == INVALID_CARGO. * @pre IsValidCargo(cargo_type) || cargo_type == INVALID_CARGO.
* @return Economy-date the industry last received cargo from a delivery, or ScriptDate::DATE_INVALID on error. * @return Economy-date the industry last received cargo from a delivery, ScriptEconomyDate::IsValid() returns false on error.
* @see \ref ScriptEconomyTime * @see \ref ScriptEconomyTime
* @api -ai * @api -ai
*/ */
static ScriptDate::Date GetCargoLastAcceptedDate(IndustryID industry_id, CargoType cargo_type); static ScriptEconomyDate *GetCargoLastAcceptedDate(IndustryID industry_id, CargoType cargo_type);
/** /**
* Get the current control flags for an industry. * Get the current control flags for an industry.

View File

@ -45,7 +45,7 @@ void SimpleCountedObject::Release()
* Get the storage associated with the current ScriptInstance. * Get the storage associated with the current ScriptInstance.
* @return The storage. * @return The storage.
*/ */
static ScriptStorage *GetStorage() static ScriptStorage &GetStorage()
{ {
return ScriptObject::GetActiveInstance().GetStorage(); return ScriptObject::GetActiveInstance().GetStorage();
} }
@ -65,7 +65,7 @@ ScriptObject::ActiveInstance::~ActiveInstance()
} }
ScriptObject::DisableDoCommandScope::DisableDoCommandScope() ScriptObject::DisableDoCommandScope::DisableDoCommandScope()
: AutoRestoreBackup(GetStorage()->allow_do_command, false) : AutoRestoreBackup(GetStorage().allow_do_command, false)
{} {}
/* static */ ScriptInstance &ScriptObject::GetActiveInstance() /* static */ ScriptInstance &ScriptObject::GetActiveInstance()
@ -78,181 +78,181 @@ ScriptObject::DisableDoCommandScope::DisableDoCommandScope()
/* static */ void ScriptObject::SetDoCommandDelay(uint ticks) /* static */ void ScriptObject::SetDoCommandDelay(uint ticks)
{ {
assert(ticks > 0); assert(ticks > 0);
GetStorage()->delay = ticks; GetStorage().delay = ticks;
} }
/* static */ uint ScriptObject::GetDoCommandDelay() /* static */ uint ScriptObject::GetDoCommandDelay()
{ {
return GetStorage()->delay; return GetStorage().delay;
} }
/* static */ void ScriptObject::SetDoCommandMode(ScriptModeProc *proc, ScriptObject *instance) /* static */ void ScriptObject::SetDoCommandMode(ScriptModeProc *proc, ScriptObject *instance)
{ {
GetStorage()->mode = proc; GetStorage().mode = proc;
GetStorage()->mode_instance = instance; GetStorage().mode_instance = instance;
} }
/* static */ ScriptModeProc *ScriptObject::GetDoCommandMode() /* static */ ScriptModeProc *ScriptObject::GetDoCommandMode()
{ {
return GetStorage()->mode; return GetStorage().mode;
} }
/* static */ ScriptObject *ScriptObject::GetDoCommandModeInstance() /* static */ ScriptObject *ScriptObject::GetDoCommandModeInstance()
{ {
return GetStorage()->mode_instance; return GetStorage().mode_instance;
} }
/* static */ void ScriptObject::SetDoCommandAsyncMode(ScriptAsyncModeProc *proc, ScriptObject *instance) /* static */ void ScriptObject::SetDoCommandAsyncMode(ScriptAsyncModeProc *proc, ScriptObject *instance)
{ {
GetStorage()->async_mode = proc; GetStorage().async_mode = proc;
GetStorage()->async_mode_instance = instance; GetStorage().async_mode_instance = instance;
} }
/* static */ ScriptAsyncModeProc *ScriptObject::GetDoCommandAsyncMode() /* static */ ScriptAsyncModeProc *ScriptObject::GetDoCommandAsyncMode()
{ {
return GetStorage()->async_mode; return GetStorage().async_mode;
} }
/* static */ ScriptObject *ScriptObject::GetDoCommandAsyncModeInstance() /* static */ ScriptObject *ScriptObject::GetDoCommandAsyncModeInstance()
{ {
return GetStorage()->async_mode_instance; return GetStorage().async_mode_instance;
} }
/* static */ void ScriptObject::SetLastCommand(const CommandDataBuffer &data, Commands cmd) /* static */ void ScriptObject::SetLastCommand(const CommandDataBuffer &data, Commands cmd)
{ {
ScriptStorage *s = GetStorage(); ScriptStorage &s = GetStorage();
Debug(script, 6, "SetLastCommand company={:02d} cmd={} data={}", s->root_company, cmd, FormatArrayAsHex(data)); Debug(script, 6, "SetLastCommand company={:02d} cmd={} data={}", s.root_company, cmd, FormatArrayAsHex(data));
s->last_data = data; s.last_data = data;
s->last_cmd = cmd; s.last_cmd = cmd;
} }
/* static */ bool ScriptObject::CheckLastCommand(const CommandDataBuffer &data, Commands cmd) /* static */ bool ScriptObject::CheckLastCommand(const CommandDataBuffer &data, Commands cmd)
{ {
ScriptStorage *s = GetStorage(); ScriptStorage &s = GetStorage();
Debug(script, 6, "CheckLastCommand company={:02d} cmd={} data={}", s->root_company, cmd, FormatArrayAsHex(data)); Debug(script, 6, "CheckLastCommand company={:02d} cmd={} data={}", s.root_company, cmd, FormatArrayAsHex(data));
if (s->last_cmd != cmd) return false; if (s.last_cmd != cmd) return false;
if (s->last_data != data) return false; if (s.last_data != data) return false;
return true; return true;
} }
/* static */ void ScriptObject::SetDoCommandCosts(Money value) /* static */ void ScriptObject::SetDoCommandCosts(Money value)
{ {
GetStorage()->costs = CommandCost(INVALID_EXPENSES, value); // Expense type is never read. GetStorage().costs = CommandCost(INVALID_EXPENSES, value); // Expense type is never read.
} }
/* static */ void ScriptObject::IncreaseDoCommandCosts(Money value) /* static */ void ScriptObject::IncreaseDoCommandCosts(Money value)
{ {
GetStorage()->costs.AddCost(value); GetStorage().costs.AddCost(value);
} }
/* static */ Money ScriptObject::GetDoCommandCosts() /* static */ Money ScriptObject::GetDoCommandCosts()
{ {
return GetStorage()->costs.GetCost(); return GetStorage().costs.GetCost();
} }
/* static */ void ScriptObject::SetLastError(ScriptErrorType last_error) /* static */ void ScriptObject::SetLastError(ScriptErrorType last_error)
{ {
GetStorage()->last_error = last_error; GetStorage().last_error = last_error;
} }
/* static */ ScriptErrorType ScriptObject::GetLastError() /* static */ ScriptErrorType ScriptObject::GetLastError()
{ {
return GetStorage()->last_error; return GetStorage().last_error;
} }
/* static */ void ScriptObject::SetLastCost(Money last_cost) /* static */ void ScriptObject::SetLastCost(Money last_cost)
{ {
GetStorage()->last_cost = last_cost; GetStorage().last_cost = last_cost;
} }
/* static */ Money ScriptObject::GetLastCost() /* static */ Money ScriptObject::GetLastCost()
{ {
return GetStorage()->last_cost; return GetStorage().last_cost;
} }
/* static */ void ScriptObject::SetRoadType(RoadType road_type) /* static */ void ScriptObject::SetRoadType(RoadType road_type)
{ {
GetStorage()->road_type = road_type; GetStorage().road_type = road_type;
} }
/* static */ RoadType ScriptObject::GetRoadType() /* static */ RoadType ScriptObject::GetRoadType()
{ {
return GetStorage()->road_type; return GetStorage().road_type;
} }
/* static */ void ScriptObject::SetRailType(RailType rail_type) /* static */ void ScriptObject::SetRailType(RailType rail_type)
{ {
GetStorage()->rail_type = rail_type; GetStorage().rail_type = rail_type;
} }
/* static */ RailType ScriptObject::GetRailType() /* static */ RailType ScriptObject::GetRailType()
{ {
return GetStorage()->rail_type; return GetStorage().rail_type;
} }
/* static */ void ScriptObject::SetLastCommandRes(bool res) /* static */ void ScriptObject::SetLastCommandRes(bool res)
{ {
GetStorage()->last_command_res = res; GetStorage().last_command_res = res;
} }
/* static */ bool ScriptObject::GetLastCommandRes() /* static */ bool ScriptObject::GetLastCommandRes()
{ {
return GetStorage()->last_command_res; return GetStorage().last_command_res;
} }
/* static */ void ScriptObject::SetLastCommandResData(CommandDataBuffer data) /* static */ void ScriptObject::SetLastCommandResData(CommandDataBuffer data)
{ {
GetStorage()->last_cmd_ret = std::move(data); GetStorage().last_cmd_ret = std::move(data);
} }
/* static */ const CommandDataBuffer &ScriptObject::GetLastCommandResData() /* static */ const CommandDataBuffer &ScriptObject::GetLastCommandResData()
{ {
return GetStorage()->last_cmd_ret; return GetStorage().last_cmd_ret;
} }
/* static */ void ScriptObject::SetCompany(::CompanyID company) /* static */ void ScriptObject::SetCompany(::CompanyID company)
{ {
if (GetStorage()->root_company == INVALID_OWNER) GetStorage()->root_company = company; if (GetStorage().root_company == INVALID_OWNER) GetStorage().root_company = company;
GetStorage()->company = company; GetStorage().company = company;
_current_company = company; _current_company = company;
} }
/* static */ ::CompanyID ScriptObject::GetCompany() /* static */ ::CompanyID ScriptObject::GetCompany()
{ {
return GetStorage()->company; return GetStorage().company;
} }
/* static */ ::CompanyID ScriptObject::GetRootCompany() /* static */ ::CompanyID ScriptObject::GetRootCompany()
{ {
return GetStorage()->root_company; return GetStorage().root_company;
} }
/* static */ bool ScriptObject::CanSuspend() /* static */ bool ScriptObject::CanSuspend()
{ {
Squirrel *squirrel = ScriptObject::GetActiveInstance().engine; Squirrel *squirrel = ScriptObject::GetActiveInstance().engine;
return GetStorage()->allow_do_command && squirrel->CanSuspend(); return GetStorage().allow_do_command && squirrel->CanSuspend();
} }
/* static */ ScriptEventQueue &ScriptObject::GetEventQueue() /* static */ ScriptEventQueue &ScriptObject::GetEventQueue()
{ {
return GetStorage()->event_queue; return GetStorage().event_queue;
} }
/* static */ ScriptLogTypes::LogData &ScriptObject::GetLogData() /* static */ ScriptLogTypes::LogData &ScriptObject::GetLogData()
{ {
return GetStorage()->log_data; return GetStorage().log_data;
} }
/* static */ void ScriptObject::SetCallbackVariable(int index, int value) /* static */ void ScriptObject::SetCallbackVariable(int index, int value)
{ {
if (static_cast<size_t>(index) >= GetStorage()->callback_value.size()) GetStorage()->callback_value.resize(index + 1); if (static_cast<size_t>(index) >= GetStorage().callback_value.size()) GetStorage().callback_value.resize(index + 1);
GetStorage()->callback_value[index] = value; GetStorage().callback_value[index] = value;
} }
/* static */ int ScriptObject::GetCallbackVariable(int index) /* static */ int ScriptObject::GetCallbackVariable(int index)
{ {
return GetStorage()->callback_value[index]; return GetStorage().callback_value[index];
} }
/* static */ CommandCallbackData *ScriptObject::GetDoCommandCallback() /* static */ CommandCallbackData *ScriptObject::GetDoCommandCallback()
@ -310,8 +310,8 @@ ScriptObject::DisableDoCommandScope::DisableDoCommandScope()
IncreaseDoCommandCosts(res.GetCost()); IncreaseDoCommandCosts(res.GetCost());
if (!_generating_world) { if (!_generating_world) {
/* Charge a nominal fee for asynchronously executed commands */ /* Charge a nominal fee for asynchronously executed commands */
Squirrel *engine = ScriptObject::GetActiveInstance().engine; Squirrel &engine = *ScriptObject::GetActiveInstance().engine;
Squirrel::DecreaseOps(engine->GetVM(), 100); Squirrel::DecreaseOps(engine.GetVM(), 100);
} }
if (callback != nullptr) { if (callback != nullptr) {
/* Insert return value into to stack and throw a control code that /* Insert return value into to stack and throw a control code that

View File

@ -179,20 +179,21 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type)
return ScriptCompany::ToScriptCompanyID(StoryPage::Get(story_page_id)->company); return ScriptCompany::ToScriptCompanyID(StoryPage::Get(story_page_id)->company);
} }
/* static */ ScriptDate::Date ScriptStoryPage::GetDate(StoryPageID story_page_id) /* static */ ScriptCalendarDate *ScriptStoryPage::GetDate(StoryPageID story_page_id)
{ {
EnforcePrecondition(ScriptDate::DATE_INVALID, IsValidStoryPage(story_page_id)); EnforcePrecondition(new ScriptCalendarDate(), IsValidStoryPage(story_page_id));
EnforceDeityMode(ScriptDate::DATE_INVALID); EnforceDeityMode(new ScriptCalendarDate());
return (ScriptDate::Date)StoryPage::Get(story_page_id)->date.base(); return new ScriptCalendarDate(static_cast<ScriptCalendarDate::Date>(StoryPage::Get(story_page_id)->date.base()));
} }
/* static */ bool ScriptStoryPage::SetDate(StoryPageID story_page_id, ScriptDate::Date date) /* static */ bool ScriptStoryPage::SetDate(StoryPageID story_page_id, ScriptCalendarDate *date)
{ {
EnforcePrecondition(false, IsValidStoryPage(story_page_id)); EnforcePrecondition(false, IsValidStoryPage(story_page_id));
EnforceDeityMode(false); EnforceDeityMode(false);
if (date == nullptr) date = new ScriptCalendarDate();
return ScriptObject::Command<CMD_SET_STORY_PAGE_DATE>::Do(story_page_id, ::TimerGameCalendar::Date{date}); return ScriptObject::Command<CMD_SET_STORY_PAGE_DATE>::Do(story_page_id, ::TimerGameCalendar::Date{date->date()});
} }

View File

@ -256,18 +256,18 @@ public:
* @pre IsValidStoryPage(story_page_id). * @pre IsValidStoryPage(story_page_id).
* @see \ref ScriptCalendarTime * @see \ref ScriptCalendarTime
*/ */
static ScriptDate::Date GetDate(StoryPageID story_page_id); static ScriptCalendarDate *GetDate(StoryPageID story_page_id);
/** /**
* Update date of a story page. The date is shown in the top left of the page * Update date of a story page. The date is shown in the top left of the page
* @param story_page_id The story page to set the date for. * @param story_page_id The story page to set the date for.
* @param date Calendar-date to display at the top of story page or ScriptDate::DATE_INVALID to disable showing date on this page. (also, @see ScriptDate) * @param date Calendar-date to display at the top of story page or null to disable showing date on this page. (also, @see ScriptCalendarDate)
* @return True if the action succeeded. * @return True if the action succeeded.
* @pre ScriptCompanyMode::IsDeity(). * @pre ScriptCompanyMode::IsDeity().
* @pre IsValidStoryPage(story_page_id). * @pre IsValidStoryPage(story_page_id).
* @see \ref ScriptCalendarTime * @see \ref ScriptCalendarTime
*/ */
static bool SetDate(StoryPageID story_page_id, ScriptDate::Date date); static bool SetDate(StoryPageID story_page_id, ScriptCalendarDate *date);
/** /**
* Update title of a story page. The title is shown in the page selector drop down. * Update title of a story page. The title is shown in the page selector drop down.

View File

@ -53,9 +53,9 @@
return ScriptCompany::ToScriptCompanyID(::Subsidy::Get(subsidy_id)->awarded); return ScriptCompany::ToScriptCompanyID(::Subsidy::Get(subsidy_id)->awarded);
} }
/* static */ ScriptDate::Date ScriptSubsidy::GetExpireDate(SubsidyID subsidy_id) /* static */ ScriptEconomyDate *ScriptSubsidy::GetExpireDate(SubsidyID subsidy_id)
{ {
if (!IsValidSubsidy(subsidy_id)) return ScriptDate::DATE_INVALID; if (!IsValidSubsidy(subsidy_id)) return new ScriptEconomyDate();
TimerGameEconomy::YearMonthDay ymd = TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::date); TimerGameEconomy::YearMonthDay ymd = TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::date);
ymd.day = 1; ymd.day = 1;
@ -63,7 +63,7 @@
ymd.month = m % 12; ymd.month = m % 12;
ymd.year += TimerGameEconomy::Year{m / 12}; ymd.year += TimerGameEconomy::Year{m / 12};
return (ScriptDate::Date)TimerGameEconomy::ConvertYMDToDate(ymd.year, ymd.month, ymd.day).base(); return ScriptEconomyDate::GetDate(ymd.year.base(), ymd.month + 1, ymd.day);
} }
/* static */ CargoType ScriptSubsidy::GetCargoType(SubsidyID subsidy_id) /* static */ CargoType ScriptSubsidy::GetCargoType(SubsidyID subsidy_id)

View File

@ -85,7 +85,7 @@ public:
* awarded. * awarded.
* @see \ref ScriptEconomyTime * @see \ref ScriptEconomyTime
*/ */
static ScriptDate::Date GetExpireDate(SubsidyID subsidy_id); static ScriptEconomyDate *GetExpireDate(SubsidyID subsidy_id);
/** /**
* Get the cargo type that has to be transported in order to be awarded this * Get the cargo type that has to be transported in order to be awarded this

View File

@ -0,0 +1,24 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../script_date.hpp"
namespace SQConvert {
/* Allow ScriptEconomyDate to be used as Squirrel parameter */
template <> struct Param<ScriptEconomyDate *> { static inline ScriptEconomyDate *Get(HSQUIRRELVM vm, int index) { return static_cast<ScriptEconomyDate *>(sq_gettype(vm, index) == OT_NULL ? nullptr : Squirrel::GetRealInstance(vm, index, "EconomyDate")); } };
template <> struct Param<ScriptEconomyDate &> { static inline ScriptEconomyDate &Get(HSQUIRRELVM vm, int index) { return *static_cast<ScriptEconomyDate *>(Squirrel::GetRealInstance(vm, index, "EconomyDate")); } };
template <> struct Param<const ScriptEconomyDate *> { static inline const ScriptEconomyDate *Get(HSQUIRRELVM vm, int index) { return static_cast<ScriptEconomyDate *>(sq_gettype(vm, index) == OT_NULL ? nullptr : Squirrel::GetRealInstance(vm, index, "EconomyDate")); } };
template <> struct Param<const ScriptEconomyDate &> { static inline const ScriptEconomyDate &Get(HSQUIRRELVM vm, int index) { return *static_cast<ScriptEconomyDate *>(Squirrel::GetRealInstance(vm, index, "EconomyDate")); } };
template <> struct Return<ScriptEconomyDate *> { static inline int Set(HSQUIRRELVM vm, ScriptEconomyDate *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "EconomyDate", res, nullptr, DefSQDestructorCallback<ScriptEconomyDate>, true); return 1; } };
/* Allow ScriptCalendarDate to be used as Squirrel parameter */
template <> struct Param<ScriptCalendarDate *> { static inline ScriptCalendarDate *Get(HSQUIRRELVM vm, int index) { return static_cast<ScriptCalendarDate *>(sq_gettype(vm, index) == OT_NULL ? nullptr : Squirrel::GetRealInstance(vm, index, "CalendarDate")); } };
template <> struct Param<ScriptCalendarDate &> { static inline ScriptCalendarDate &Get(HSQUIRRELVM vm, int index) { return *static_cast<ScriptCalendarDate *>(Squirrel::GetRealInstance(vm, index, "CalendarDate")); } };
template <> struct Param<const ScriptCalendarDate *> { static inline const ScriptCalendarDate *Get(HSQUIRRELVM vm, int index) { return static_cast<ScriptCalendarDate *>(sq_gettype(vm, index) == OT_NULL ? nullptr : Squirrel::GetRealInstance(vm, index, "CalendarDate")); } };
template <> struct Param<const ScriptCalendarDate &> { static inline const ScriptCalendarDate &Get(HSQUIRRELVM vm, int index) { return *static_cast<ScriptCalendarDate *>(Squirrel::GetRealInstance(vm, index, "CalendarDate")); } };
template <> struct Return<ScriptCalendarDate *> { static inline int Set(HSQUIRRELVM vm, ScriptCalendarDate *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "CalendarDate", res, nullptr, DefSQDestructorCallback<ScriptCalendarDate>, true); return 1; } };
} // namespace SQConvert

View File

@ -100,7 +100,7 @@ void ScriptInstance::Initialize(const std::string &main_script, const std::strin
void ScriptInstance::RegisterAPI() void ScriptInstance::RegisterAPI()
{ {
squirrel_register_std(this->engine); squirrel_register_std(*this->engine);
} }
bool ScriptInstance::LoadCompatibilityScript(std::string_view api_version, Subdirectory dir) bool ScriptInstance::LoadCompatibilityScript(std::string_view api_version, Subdirectory dir)
@ -318,9 +318,10 @@ void ScriptInstance::CollectGarbage()
} }
ScriptStorage *ScriptInstance::GetStorage() ScriptStorage &ScriptInstance::GetStorage()
{ {
return this->storage; assert(this->storage != nullptr);
return *this->storage;
} }
ScriptLogTypes::LogData &ScriptInstance::GetLogData() ScriptLogTypes::LogData &ScriptInstance::GetLogData()

View File

@ -91,7 +91,7 @@ public:
/** /**
* Get the storage of this script. * Get the storage of this script.
*/ */
class ScriptStorage *GetStorage(); class ScriptStorage &GetStorage();
/** /**
* Get the log pointer of this script. * Get the log pointer of this script.
@ -146,7 +146,11 @@ public:
/** /**
* Get the controller attached to the instance. * Get the controller attached to the instance.
*/ */
class ScriptController *GetController() { return controller; } class ScriptController &GetController()
{
assert(this->controller != nullptr);
return *this->controller;
}
/** /**
* Return the "this script died" value * Return the "this script died" value

View File

@ -536,7 +536,7 @@ void Squirrel::Initialize()
sq_setforeignptr(this->vm, this); sq_setforeignptr(this->vm, this);
sq_pushroottable(this->vm); sq_pushroottable(this->vm);
squirrel_register_global_std(this); squirrel_register_global_std(*this);
/* Set consts table as delegate of root table, so consts/enums defined via require() are accessible */ /* Set consts table as delegate of root table, so consts/enums defined via require() are accessible */
sq_pushconsttable(this->vm); sq_pushconsttable(this->vm);

View File

@ -82,20 +82,20 @@ SQInteger SquirrelStd::notifyallexceptions(HSQUIRRELVM vm)
return SQ_ERROR; return SQ_ERROR;
} }
void squirrel_register_global_std(Squirrel *engine) void squirrel_register_global_std(Squirrel &engine)
{ {
/* We don't use squirrel_helper here, as we want to register to the global /* We don't use squirrel_helper here, as we want to register to the global
* scope and not to a class. */ * scope and not to a class. */
engine->AddMethod("require", &SquirrelStd::require, ".s"); engine.AddMethod("require", &SquirrelStd::require, ".s");
engine->AddMethod("notifyallexceptions", &SquirrelStd::notifyallexceptions, ".b"); engine.AddMethod("notifyallexceptions", &SquirrelStd::notifyallexceptions, ".b");
} }
void squirrel_register_std(Squirrel *engine) void squirrel_register_std(Squirrel &engine)
{ {
/* We don't use squirrel_helper here, as we want to register to the global /* We don't use squirrel_helper here, as we want to register to the global
* scope and not to a class. */ * scope and not to a class. */
engine->AddMethod("min", &SquirrelStd::min, ".ii"); engine.AddMethod("min", &SquirrelStd::min, ".ii");
engine->AddMethod("max", &SquirrelStd::max, ".ii"); engine.AddMethod("max", &SquirrelStd::max, ".ii");
sqstd_register_mathlib(engine->GetVM()); sqstd_register_mathlib(engine.GetVM());
} }

View File

@ -52,12 +52,12 @@ public:
/** /**
* Register all standard functions we want to give to a script. * Register all standard functions we want to give to a script.
*/ */
void squirrel_register_std(Squirrel *engine); void squirrel_register_std(Squirrel &engine);
/** /**
* Register all standard functions that are available on first startup. * Register all standard functions that are available on first startup.
* @note this set is very limited, and is only meant to load other scripts and things like that. * @note this set is very limited, and is only meant to load other scripts and things like that.
*/ */
void squirrel_register_global_std(Squirrel *engine); void squirrel_register_global_std(Squirrel &engine);
#endif /* SQUIRREL_STD_HPP */ #endif /* SQUIRREL_STD_HPP */

View File

@ -3331,7 +3331,7 @@ draw_default_foundation:
auto result = GetRoadStopLayout(ti, stopspec, st, type, view, regs100); auto result = GetRoadStopLayout(ti, stopspec, st, type, view, regs100);
if (result.has_value()) { if (result.has_value()) {
if (stopspec->flags.Test(RoadStopSpecFlag::DrawModeRegister)) { if (stopspec->flags.Test(RoadStopSpecFlag::DrawModeRegister)) {
stop_draw_mode = static_cast<RoadStopDrawMode>(regs100[0]); stop_draw_mode = static_cast<RoadStopDrawModes>(regs100[0]);
} }
if (type == StationType::RoadWaypoint && stop_draw_mode.Test(RoadStopDrawMode::WaypGround)) { if (type == StationType::RoadWaypoint && stop_draw_mode.Test(RoadStopDrawMode::WaypGround)) {
draw_ground = true; draw_ground = true;

View File

@ -427,6 +427,7 @@ struct TimetableWindow : Window {
void DrawTimetablePanel(const Rect &r) const void DrawTimetablePanel(const Rect &r) const
{ {
const Vehicle *v = this->vehicle; const Vehicle *v = this->vehicle;
if (v->GetNumOrders() == 0) return;
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect); Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
int i = this->vscroll->GetPosition(); int i = this->vscroll->GetPosition();
VehicleOrderID order_id = (i + 1) / 2; VehicleOrderID order_id = (i + 1) / 2;