Different approach to a daylength mod/patch.

Forum for technical discussions regarding development. If you have a general suggestion, problem or comment, please use one of the other forums.

Moderator: OpenTTD Developers

Post Reply
RafaelF82
Engineer
Engineer
Posts: 2
Joined: 16 Sep 2014 18:26

Different approach to a daylength mod/patch.

Post by RafaelF82 »

I was looking at the source code hoping to mod it to have longer days and I also found numerous patches that change the DAY_TICKS variable and then need to change numerous things that come with changing this.

Anyway I then noticed that the change could be made elsewhere so maybe you guys more familiar with the code can confirm if I'm not missing anything ?

I noticed that I didn't want to change how the daily loop works, I just want days to take longer but I wanted everything else to continue working as they do today so instead of changing DAY_TICKS I noticed I should change the passing of days instead.

So I found where this happened and noticed the _date variable is where the days are kept. Whenever _date_fract > DAY_TICKS we then have _date++ and everything else that happens when days change.

Current original version :

Code: Select all

void IncreaseDate()
{
	/* increase day, and check if a new day is there? */
	_tick_counter++;

	if (_game_mode == GM_MENU) return;

	_date_fract++;
	if (_date_fract < DAY_TICKS) return;
	_date_fract = 0;

	/* increase day counter */
	_date++;

	YearMonthDay ymd;
	ConvertDateToYMD(_date, &ymd);

	/* check if we entered a new month? */
	bool new_month = ymd.month != _cur_month;

	/* check if we entered a new year? */
	bool new_year = ymd.year != _cur_year;

	/* update internal variables before calling the daily/monthly/yearly loops */
	_cur_month = ymd.month;
	_cur_year  = ymd.year;

	/* yes, call various daily loops */
	OnNewDay();

	/* yes, call various monthly loops */
	if (new_month) OnNewMonth();

	/* yes, call various yearly loops */
	if (new_year) OnNewYear();
}
Well what if instead of changing DAY_TICKS I just took longer to make _date++;, but kept running everything else that needs to run, lets say I want to change how the game works today so instead of a new day ever ~2 seconds we get a new hour ?

The method would look like this :

Code: Select all


int32 _hour; // initialize this when new game or load a existing game

void IncreaseDate()
{
	/* increase day, and check if a new day is there? */
	_tick_counter++;

	if (_game_mode == GM_MENU) return;

	_date_fract++;
	if (_date_fract < DAY_TICKS) return;
	_date_fract = 0;

        _hour++;
	/* increase day counter */
        if(_hour > 23)
        {
	       _date++; // date is only incremented once every 24 hours instead of every 2 seconds.
               _hour = 0;
        }

	YearMonthDay ymd;
	ConvertDateToYMD(_date, &ymd);

	/* check if we entered a new month? */
	bool new_month = ymd.month != _cur_month;

	/* check if we entered a new year? */
	bool new_year = ymd.year != _cur_year;

	/* update internal variables before calling the daily/monthly/yearly loops */
	_cur_month = ymd.month;
	_cur_year  = ymd.year;

	/* yes, call various daily loops */
	OnNewDay();

	/* yes, call various monthly loops */
	if (new_month) OnNewMonth();

	/* yes, call various yearly loops */
	if (new_year) OnNewYear();
}

The only other change I noticed that would be required is in town growth code, because otherwise towns would grow too large.

Question is, do you guys think this is correct ? Did I miss something else ?



EDIT: I tested a little and noticed I missed the monthly infrastructure and loan costs, otherwise the game would be even easier, I multiplied these costs by the number of hours I left in the day, so they cost 24 times more just as the months take 24 times more to change. I also noticed the yearly running costs for the vehicles, although they are correctly calculated, are displayed wrongly wherever they are displayed, I'll try to find it now.



EDIT2 : I believe I did everything that was needed, I made town growth take longer, I made infrastructure and loan costs that are monthly calculated be multiplied by however longer the days are, and I fixed the yearly running costs display on vehicles. Now I need to find how do I save this new variable _hour I created so it properly saves the current time of day. Can anyone point in the right direction ? I'm looking everywhere for where _date is saved and can't find it.
User avatar
ChillCore
Tycoon
Tycoon
Posts: 2822
Joined: 04 Oct 2008 23:05
Location: Lost in spaces

Re: Different approach to a daylength mod/patch.

Post by ChillCore »

RafaelF82 wrote: I'm looking everywhere for where _date is saved and can't find it.
You may want to download the documentation bundle to find things more easily https://www.openttd.org/en/download-trunk.
Getting a daylength patch to work correctly is a hard thing to do indeed.

Welcome to the forums. ;)
-- .- -.-- / - .... . / ..-. --- .-. -.-. . / -... . / .-- .. - .... / -.-- --- ..- .-.-.-
--- .... / -.-- . .- .... --..-- / .- -. -.. / .--. .-. .- .. ... . / - .... . / .-.. --- .-. -.. / ..-. --- .-. / .... . / --. .- ...- . / ..- ... / -.-. .... --- --- -.-. .... --- --- ... .-.-.- / ---... .--.

Playing with my patchpack? Ask questions on usage and report bugs in the correct thread first, please.
All included patches have been modified and are no longer 100% original.
RafaelF82
Engineer
Engineer
Posts: 2
Joined: 16 Sep 2014 18:26

Re: Different approach to a daylength mod/patch.

Post by RafaelF82 »

Thanks, I did find how the time is saved, but I used a settings "hack" to get the job done and it worked perfectly. I can use the settings screen to check the current hour and it saves correctly with the save game ;)

The modifications I made seem to be working great so far.

The monthly costs are correctly calculated and the engines costs are being correctly calculated too since they're happening exactly like they always did.

The towns also seem to be keeping the expected growth so far.

The only odd thing is that monthly stuff gets, well, different, cause on the first month the industry productions are shown as if the month had about 30 ticks, since now my month has 24x that, after the month turns their monthly production numbers get really high, but still, they get correct.

Doing the modification by delaying the addition to date made it easy to get it working, the only things that got a bit off were the montly expenses but since I multiplied them too, it seems ok now.





EDIT :

I made a patch/diff file using subversion, in case anyone wants to know the changes and apply it themselves, this will work for 24 hours in a day only, because in 2 places (vehicle_base.h and date_type.h) I didn't make it take the number of hours from the settings, which I plan to fix in the future.

The current issues :

- Since I wanted to not mess with game balance, the vehicles get old as they did in the original version, since years take 24 more ticks to pass by you will see the vehicles age counter wrongly, but this is a display issue only, I'm probably going to fix the display by saying vehicles ages in months and properly measuring them, so if you take 24 hours to pass a day this means a vehicle that lasted for 15 years will last for :
15 years ~= 5475 game ticks, since a day is now 24 ticks instead of 1, the vehicle will last for ~7.6 months. (not exactly that but that's how it practically is)

- The yearly running cost of new vehicles is displayed wrongly, once you buy the vehicle the costs are correctly displayed and calculated.

- I think the infrastructure costs are displayed wrongly on the infrastructure screen, but they are correct on the income statement screen and correctly calculated (costing 24x more monthly).

- Save game will be incompatible with any other version because I'm using the settings to save the current hour, I'll still need to learn how to fix this.

Code: Select all

Index: src/date.cpp
===================================================================
--- src/date.cpp	(revision 26827)
+++ src/date.cpp	(working copy)
 
@@ -284,7 +287,13 @@
 	_date_fract = 0;
 
 	/* increase day counter */
-	_date++;
+	_settings_game.economy.current_hour++;
+	if(_settings_game.economy.current_hour >= _settings_game.economy.number_of_hours)
+	{
+		_date++;
+		_settings_game.economy.current_hour = 0;
+	}
 
 	YearMonthDay ymd;
 	ConvertDateToYMD(_date, &ymd);
Index: src/date_type.h
===================================================================
--- src/date_type.h	(revision 26827)
+++ src/date_type.h	(working copy)
@@ -36,7 +37,7 @@
 static const int STATION_LINKGRAPH_TICKS  = 504; ///< cycle duration for cleaning dead links
 static const int CARGO_AGING_TICKS        = 185; ///< cycle duration for aging cargo
 static const int INDUSTRY_PRODUCE_TICKS   = 256; ///< cycle duration for industry production
-static const int TOWN_GROWTH_TICKS        = 70;  ///< cycle duration for towns trying to grow. (this originates from the size of the town array in TTD
+static const int TOWN_GROWTH_TICKS        = 70 * 24;  ///< cycle duration for towns trying to grow. (this originates from the size of the town array in TTD
 static const int INDUSTRY_CUT_TREE_TICKS  = INDUSTRY_PRODUCE_TICKS * 2; ///< cycle duration for lumber mill's extra action
 
 
Index: src/economy.cpp
===================================================================
--- src/economy.cpp	(revision 26827)
+++ src/economy.cpp	(working copy)
@@ -635,7 +635,7 @@
 	if (!_settings_game.economy.infrastructure_maintenance) {
 		FOR_ALL_STATIONS(st) {
 			cur_company.Change(st->owner);
-			CommandCost cost(EXPENSES_PROPERTY, _price[PR_STATION_VALUE] >> 1);
+			CommandCost cost(EXPENSES_PROPERTY, (_price[PR_STATION_VALUE] >> 1 * _settings_game.economy.number_of_hours));
 			SubtractMoneyFromCompany(cost);
 		}
 	} else {
@@ -646,15 +646,15 @@
 			CommandCost cost(EXPENSES_PROPERTY);
 			uint32 rail_total = c->infrastructure.GetRailTotal();
 			for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
-				if (c->infrastructure.rail[rt] != 0) cost.AddCost(RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
+				if (c->infrastructure.rail[rt] != 0) cost.AddCost(RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total) * _settings_game.economy.number_of_hours);
 			}
-			cost.AddCost(SignalMaintenanceCost(c->infrastructure.signal));
+			cost.AddCost(SignalMaintenanceCost(c->infrastructure.signal) * _settings_game.economy.number_of_hours);
 			for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
-				if (c->infrastructure.road[rt] != 0) cost.AddCost(RoadMaintenanceCost(rt, c->infrastructure.road[rt]));
+				if (c->infrastructure.road[rt] != 0) cost.AddCost(RoadMaintenanceCost(rt, c->infrastructure.road[rt]) * _settings_game.economy.number_of_hours);
 			}
-			cost.AddCost(CanalMaintenanceCost(c->infrastructure.water));
-			cost.AddCost(StationMaintenanceCost(c->infrastructure.station));
-			cost.AddCost(AirportMaintenanceCost(c->index));
+			cost.AddCost(CanalMaintenanceCost(c->infrastructure.water) * _settings_game.economy.number_of_hours);
+			cost.AddCost(StationMaintenanceCost(c->infrastructure.station) * _settings_game.economy.number_of_hours);
+			cost.AddCost(AirportMaintenanceCost(c->index) * _settings_game.economy.number_of_hours);
 
 			SubtractMoneyFromCompany(cost);
 		}
@@ -818,7 +818,7 @@
 		 * In order to prevent cheating or abuse (just not paying interest by not
 		 * taking a loan we make companies pay interest on negative cash as well
 		 */
-		Money yearly_fee = c->current_loan * _economy.interest_rate / 100;
+		Money yearly_fee = (c->current_loan * _economy.interest_rate / 100) * _settings_game.economy.number_of_hours;
 		if (c->money < 0) {
 			yearly_fee += -c->money *_economy.interest_rate / 100;
 		}
@@ -827,7 +827,7 @@
 
 		SubtractMoneyFromCompany(CommandCost(EXPENSES_LOAN_INT, up_to_this_month - up_to_previous_month));
 
-		SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, _price[PR_STATION_VALUE] >> 2));
+		SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, (_price[PR_STATION_VALUE] >> 2) * _settings_game.economy.number_of_hours));
 	}
 	cur_company.Restore();
 }
Index: src/settings_gui.cpp
===================================================================
--- src/settings_gui.cpp	(revision 26827)
+++ src/settings_gui.cpp	(working copy)
@@ -1568,6 +1568,8 @@
 			accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
 			accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
 			accounting->Add(new SettingEntry("difficulty.construction_cost"));
+			accounting->Add(new SettingEntry("economy.number_of_hours"));
+			accounting->Add(new SettingEntry("economy.current_hour"));
 		}
 
 		SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
Index: src/settings_type.h
===================================================================
--- src/settings_type.h	(revision 26827)
+++ src/settings_type.h	(working copy)
@@ -486,6 +486,8 @@
 	uint16 town_noise_population[3];         ///< population to base decision on noise evaluation (@see town_council_tolerance)
 	bool   allow_town_level_crossings;       ///< towns are allowed to build level crossings
 	bool   infrastructure_maintenance;       ///< enable monthly maintenance fee for owner infrastructure
+	uint8  number_of_hours;                  ///< The number of hours in a day
+    uint8  current_hour;                     ///< The current hour
 };
 
 struct LinkGraphSettings {
Index: src/vehicle_base.h
===================================================================
--- src/vehicle_base.h	(revision 26827)
+++ src/vehicle_base.h	(working copy)
@@ -499,7 +499,7 @@
 	 * Gets the running cost of a vehicle  that can be sent into SetDParam for string processing.
 	 * @return the vehicle's running cost
 	 */
-	Money GetDisplayRunningCost() const { return (this->GetRunningCost() >> 8); }
+	Money GetDisplayRunningCost() const { return ((this->GetRunningCost() * 24) >> 8); }
 
 	/**
 	 * Gets the profit vehicle had this year. It can be sent into SetDParam for string processing.
Also add to settings.ini

Code: Select all

[SDT_VAR]
base     = GameSettings
var      = economy.number_of_hours
type     = SLE_UINT8
from     = 193
to       = SL_MAX_VERSION
flags    = 0
guiflags = 0
def      = 24
min      = 1
max      = 100
interval = 1
str      = STR_CONFIG_SETTING_SET_HOURS_IN_DAY
strhelp  = STR_CONFIG_SETTING_SET_HOURS_IN_DAY_HELPTEXT
strval   = STR_JUST_INT

[SDT_VAR]
base     = GameSettings
var      = economy.current_hour
type     = SLE_UINT8
from     = 193
to       = SL_MAX_VERSION
flags    = 0
guiflags = SGF_0ISDISABLED
def      = 0
min      = 0
max      = 100
interval = 1
str      = STR_CONFIG_SETTING_CURRENT_HOUR
strhelp  = STR_CONFIG_SETTING_CURRENT_HOUR_HELPTEXT
strval   = STR_JUST_INT
And to english.txt

Code: Select all

STR_CONFIG_SETTING_SET_HOURS_IN_DAY                             :{LTBLUE}How many hours are in a day {ORANGE}{STRING2}
STR_CONFIG_SETTING_SET_HOURS_IN_DAY_HELPTEXT                    :Sets how much longer days should be.
STR_CONFIG_SETTING_CURRENT_HOUR                                 :{LTBLUE}Displays the current hour {ORANGE}{STRING2} 
STR_CONFIG_SETTING_CURRENT_HOUR_HELPTEXT                        :Displays the current hour
Openend
Engineer
Engineer
Posts: 36
Joined: 18 Jun 2015 09:09

Re: Different approach to a daylength mod/patch.

Post by Openend »

I found this on Reddit.

@Rafeael
Thanks a lot!
This seems to be exactly the thing a daylenght patch should be doing. Why aren't there more people posting in this topic? Are there any bugs/glitches with this patch? (other than what you already posted)

Anyway, I cant wait to test it out
Post Reply

Return to “OpenTTD Development”

Who is online

Users browsing this forum: No registered users and 53 guests