changeset 18774:1fa19d70aea9 draft

(svn r23622) -Add: a set of events to trigger in a GameScript
author truebrain <truebrain@openttd.org>
date Mon, 19 Dec 2011 20:59:36 +0000
parents 3d03f5c4bbc1
children 26ffd3067724
files src/aircraft_cmd.cpp src/company_cmd.cpp src/disaster_cmd.cpp src/economy.cpp src/game/game.hpp src/game/game_core.cpp src/game/game_instance.cpp src/industry_cmd.cpp src/roadveh_cmd.cpp src/script/api/game/game_event_types.hpp.sq src/script/api/script_event_types.hpp src/subsidy.cpp src/town_cmd.cpp src/train_cmd.cpp src/water_cmd.cpp
diffstat 15 files changed, 310 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/aircraft_cmd.cpp
+++ b/src/aircraft_cmd.cpp
@@ -29,6 +29,7 @@
 #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"
@@ -1160,6 +1161,7 @@
 	}
 
 	AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, st == NULL ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
+	Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, st == NULL ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
 
 	AddVehicleNewsItem(newsitem,
 		NS_ACCIDENT,
@@ -1225,6 +1227,7 @@
 			st->index
 		);
 		AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
+		Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
 	}
 
 	v->BeginLoading();
--- a/src/company_cmd.cpp
+++ b/src/company_cmd.cpp
@@ -35,6 +35,7 @@
 #include "vehicle_func.h"
 #include "sprite.h"
 #include "smallmap_gui.h"
+#include "game/game.hpp"
 
 #include "table/strings.h"
 
@@ -563,6 +564,7 @@
 	if (is_ai && (!_networking || _network_server)) AI::StartNew(c->index);
 
 	AI::BroadcastNewEvent(new ScriptEventCompanyNew(c->index), c->index);
+	Game::NewEvent(new ScriptEventCompanyNew(c->index));
 
 	return c;
 }
@@ -905,6 +907,7 @@
 			CompanyID c_index = c->index;
 			delete c;
 			AI::BroadcastNewEvent(new ScriptEventCompanyBankrupt(c_index));
+			Game::NewEvent(new ScriptEventCompanyBankrupt(c_index));
 			CompanyAdminRemove(c_index, (CompanyRemoveReason)reason);
 			break;
 		}
--- a/src/disaster_cmd.cpp
+++ b/src/disaster_cmd.cpp
@@ -40,6 +40,7 @@
 #include "effectvehicle_func.h"
 #include "roadveh.h"
 #include "ai/ai.hpp"
+#include "game/game.hpp"
 #include "company_base.h"
 #include "core/random_func.hpp"
 #include "core/backup_type.hpp"
@@ -358,6 +359,7 @@
 					u->index); // delete the news, when the roadvehicle is gone
 
 				AI::NewEvent(u->owner, new ScriptEventVehicleCrashed(u->index, u->tile, ScriptEventVehicleCrashed::CRASH_RV_UFO));
+				Game::NewEvent(new ScriptEventVehicleCrashed(u->index, u->tile, ScriptEventVehicleCrashed::CRASH_RV_UFO));
 			}
 		}
 
--- a/src/economy.cpp
+++ b/src/economy.cpp
@@ -47,6 +47,7 @@
 #include "newgrf.h"
 #include "core/backup_type.hpp"
 #include "water.h"
+#include "game/game.hpp"
 
 #include "table/strings.h"
 #include "table/pricebase.h"
@@ -536,6 +537,7 @@
 			SetDParamStr(2, cni->company_name);
 			AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, NS_COMPANY_TROUBLE, cni);
 			AI::BroadcastNewEvent(new ScriptEventCompanyInTrouble(c->index));
+			Game::NewEvent(new ScriptEventCompanyInTrouble(c->index));
 			break;
 		}
 
@@ -1644,6 +1646,7 @@
 	SetDParam(4, c->bankrupt_value);
 	AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, NS_COMPANY_MERGER, cni);
 	AI::BroadcastNewEvent(new ScriptEventCompanyMerger(ci, _current_company));
+	Game::NewEvent(new ScriptEventCompanyMerger(ci, _current_company));
 
 	ChangeOwnershipOfCompanyItems(ci, _current_company);
 
--- a/src/game/game.hpp
+++ b/src/game/game.hpp
@@ -18,6 +18,8 @@
 /** A list that maps AI names to their AIInfo object. */
 typedef std::map<const char *, class ScriptInfo *, StringCompare> ScriptInfoList;
 
+#include "../script/api/script_event_types.hpp"
+
 /**
  * Main Game class. Contains all functions needed to start, stop, save and load Game Scripts.
  */
@@ -44,6 +46,11 @@
 	static void Uninitialize(bool keepConfig);
 
 	/**
+	 * Queue a new event for a Game Script.
+	 */
+	static void NewEvent(class ScriptEvent *event);
+
+	/**
 	 * Get the current GameScript instance.
 	 */
 	static class GameInstance *GetGameInstance() { return Game::instance; }
--- a/src/game/game_core.cpp
+++ b/src/game/game_core.cpp
@@ -109,6 +109,31 @@
 	}
 }
 
+/* static */ void Game::NewEvent(ScriptEvent *event)
+{
+	/* AddRef() and Release() need to be called at least once, so do it here */
+	event->AddRef();
+
+	/* Clients should ignore events */
+	if (_networking && !_network_server) {
+		event->Release();
+		return;
+	}
+
+	/* Check if Game instance is alive */
+	if (Game::instance == NULL) {
+		event->Release();
+		return;
+	}
+
+	/* Queue the event */
+	Backup<CompanyByte> cur_company(_current_company, OWNER_DEITY, FILE_LINE);
+	Game::instance->InsertEvent(event);
+	cur_company.Restore();
+
+	event->Release();
+}
+
 /* static */ void Game::ResetConfig()
 {
 	/* Check for both newgame as current game if we can reload the GameInfo insde
--- a/src/game/game_instance.cpp
+++ b/src/game/game_instance.cpp
@@ -39,6 +39,7 @@
 #include "../script/api/game/game_enginelist.hpp.sq"
 #include "../script/api/game/game_error.hpp.sq"
 #include "../script/api/game/game_event.hpp.sq"
+#include "../script/api/game/game_event_types.hpp.sq"
 #include "../script/api/game/game_execmode.hpp.sq"
 #include "../script/api/game/game_game.hpp.sq"
 #include "../script/api/game/game_gamesettings.hpp.sq"
@@ -109,7 +110,20 @@
 	SQGSEngineList_Register(this->engine);
 	SQGSError_Register(this->engine);
 	SQGSEvent_Register(this->engine);
+	SQGSEventCompanyBankrupt_Register(this->engine);
+	SQGSEventCompanyInTrouble_Register(this->engine);
+	SQGSEventCompanyMerger_Register(this->engine);
+	SQGSEventCompanyNew_Register(this->engine);
 	SQGSEventController_Register(this->engine);
+	SQGSEventIndustryClose_Register(this->engine);
+	SQGSEventIndustryOpen_Register(this->engine);
+	SQGSEventStationFirstVehicle_Register(this->engine);
+	SQGSEventSubsidyAwarded_Register(this->engine);
+	SQGSEventSubsidyExpired_Register(this->engine);
+	SQGSEventSubsidyOffer_Register(this->engine);
+	SQGSEventSubsidyOfferExpired_Register(this->engine);
+	SQGSEventTownFounded_Register(this->engine);
+	SQGSEventVehicleCrashed_Register(this->engine);
 	SQGSExecMode_Register(this->engine);
 	SQGSGame_Register(this->engine);
 	SQGSGameSettings_Register(this->engine);
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -39,6 +39,7 @@
 #include "subsidy_func.h"
 #include "core/backup_type.hpp"
 #include "object_base.h"
+#include "game/game.hpp"
 
 #include "table/strings.h"
 #include "table/industry_land.h"
@@ -482,6 +483,7 @@
 
 	if (flags & DC_EXEC) {
 		AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
+		Game::NewEvent(new ScriptEventIndustryClose(i->index));
 		delete i;
 	}
 	return CommandCost(EXPENSES_CONSTRUCTION, indspec->GetRemovalCost());
@@ -1876,6 +1878,7 @@
 		}
 		AddIndustryNewsItem(indspec->new_industry_text, NS_INDUSTRY_OPEN, ind->index);
 		AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
+		Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
 	}
 
 	return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
@@ -1989,6 +1992,7 @@
 	}
 	AddIndustryNewsItem(ind_spc->new_industry_text, NS_INDUSTRY_OPEN, ind->index);
 	AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
+	Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
 }
 
 /**
@@ -2597,6 +2601,7 @@
 		if (closeit) {
 			ns = NS_INDUSTRY_CLOSE;
 			AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
+			Game::NewEvent(new ScriptEventIndustryClose(i->index));
 		} else {
 			switch (WhoCanServiceIndustry(i)) {
 				case 0: ns = NS_INDUSTRY_NOBODY;  break;
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -27,6 +27,7 @@
 #include "vehicle_func.h"
 #include "sound_func.h"
 #include "ai/ai.hpp"
+#include "game/game.hpp"
 #include "depot_map.h"
 #include "effectvehicle_func.h"
 #include "roadstop_base.h"
@@ -521,6 +522,7 @@
 	uint pass = v->Crash();
 
 	AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING));
+	Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING));
 
 	SetDParam(0, pass);
 	AddVehicleNewsItem(
@@ -669,6 +671,7 @@
 				st->index
 			);
 			AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
+			Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
 		}
 	} else {
 		/* Check if station was ever visited before */
@@ -682,6 +685,7 @@
 				st->index
 			);
 			AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
+			Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
 		}
 	}
 }
new file mode 100644
--- /dev/null
+++ b/src/script/api/game/game_event_types.hpp.sq
@@ -0,0 +1,219 @@
+/* $Id$ */
+
+/*
+ * 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/>.
+ */
+
+/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
+
+#include "../script_event_types.hpp"
+#include "../template/template_event_types.hpp.sq"
+
+
+template <> const char *GetClassName<ScriptEventVehicleCrashed, ST_GS>() { return "GSEventVehicleCrashed"; }
+
+void SQGSEventVehicleCrashed_Register(Squirrel *engine)
+{
+	DefSQClass<ScriptEventVehicleCrashed, ST_GS> SQGSEventVehicleCrashed("GSEventVehicleCrashed");
+	SQGSEventVehicleCrashed.PreRegister(engine, "GSEvent");
+
+	SQGSEventVehicleCrashed.DefSQConst(engine, ScriptEventVehicleCrashed::CRASH_TRAIN,               "CRASH_TRAIN");
+	SQGSEventVehicleCrashed.DefSQConst(engine, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING,   "CRASH_RV_LEVEL_CROSSING");
+	SQGSEventVehicleCrashed.DefSQConst(engine, ScriptEventVehicleCrashed::CRASH_RV_UFO,              "CRASH_RV_UFO");
+	SQGSEventVehicleCrashed.DefSQConst(engine, ScriptEventVehicleCrashed::CRASH_PLANE_LANDING,       "CRASH_PLANE_LANDING");
+	SQGSEventVehicleCrashed.DefSQConst(engine, ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT, "CRASH_AIRCRAFT_NO_AIRPORT");
+	SQGSEventVehicleCrashed.DefSQConst(engine, ScriptEventVehicleCrashed::CRASH_FLOODED,             "CRASH_FLOODED");
+
+	SQGSEventVehicleCrashed.DefSQStaticMethod(engine, &ScriptEventVehicleCrashed::Convert, "Convert", 2, ".x");
+
+	SQGSEventVehicleCrashed.DefSQMethod(engine, &ScriptEventVehicleCrashed::GetVehicleID,   "GetVehicleID",   1, "x");
+	SQGSEventVehicleCrashed.DefSQMethod(engine, &ScriptEventVehicleCrashed::GetCrashSite,   "GetCrashSite",   1, "x");
+	SQGSEventVehicleCrashed.DefSQMethod(engine, &ScriptEventVehicleCrashed::GetCrashReason, "GetCrashReason", 1, "x");
+
+	SQGSEventVehicleCrashed.PostRegister(engine);
+}
+
+
+template <> const char *GetClassName<ScriptEventSubsidyOffer, ST_GS>() { return "GSEventSubsidyOffer"; }
+
+void SQGSEventSubsidyOffer_Register(Squirrel *engine)
+{
+	DefSQClass<ScriptEventSubsidyOffer, ST_GS> SQGSEventSubsidyOffer("GSEventSubsidyOffer");
+	SQGSEventSubsidyOffer.PreRegister(engine, "GSEvent");
+
+	SQGSEventSubsidyOffer.DefSQStaticMethod(engine, &ScriptEventSubsidyOffer::Convert, "Convert", 2, ".x");
+
+	SQGSEventSubsidyOffer.DefSQMethod(engine, &ScriptEventSubsidyOffer::GetSubsidyID, "GetSubsidyID", 1, "x");
+
+	SQGSEventSubsidyOffer.PostRegister(engine);
+}
+
+
+template <> const char *GetClassName<ScriptEventSubsidyOfferExpired, ST_GS>() { return "GSEventSubsidyOfferExpired"; }
+
+void SQGSEventSubsidyOfferExpired_Register(Squirrel *engine)
+{
+	DefSQClass<ScriptEventSubsidyOfferExpired, ST_GS> SQGSEventSubsidyOfferExpired("GSEventSubsidyOfferExpired");
+	SQGSEventSubsidyOfferExpired.PreRegister(engine, "GSEvent");
+
+	SQGSEventSubsidyOfferExpired.DefSQStaticMethod(engine, &ScriptEventSubsidyOfferExpired::Convert, "Convert", 2, ".x");
+
+	SQGSEventSubsidyOfferExpired.DefSQMethod(engine, &ScriptEventSubsidyOfferExpired::GetSubsidyID, "GetSubsidyID", 1, "x");
+
+	SQGSEventSubsidyOfferExpired.PostRegister(engine);
+}
+
+
+template <> const char *GetClassName<ScriptEventSubsidyAwarded, ST_GS>() { return "GSEventSubsidyAwarded"; }
+
+void SQGSEventSubsidyAwarded_Register(Squirrel *engine)
+{
+	DefSQClass<ScriptEventSubsidyAwarded, ST_GS> SQGSEventSubsidyAwarded("GSEventSubsidyAwarded");
+	SQGSEventSubsidyAwarded.PreRegister(engine, "GSEvent");
+
+	SQGSEventSubsidyAwarded.DefSQStaticMethod(engine, &ScriptEventSubsidyAwarded::Convert, "Convert", 2, ".x");
+
+	SQGSEventSubsidyAwarded.DefSQMethod(engine, &ScriptEventSubsidyAwarded::GetSubsidyID, "GetSubsidyID", 1, "x");
+
+	SQGSEventSubsidyAwarded.PostRegister(engine);
+}
+
+
+template <> const char *GetClassName<ScriptEventSubsidyExpired, ST_GS>() { return "GSEventSubsidyExpired"; }
+
+void SQGSEventSubsidyExpired_Register(Squirrel *engine)
+{
+	DefSQClass<ScriptEventSubsidyExpired, ST_GS> SQGSEventSubsidyExpired("GSEventSubsidyExpired");
+	SQGSEventSubsidyExpired.PreRegister(engine, "GSEvent");
+
+	SQGSEventSubsidyExpired.DefSQStaticMethod(engine, &ScriptEventSubsidyExpired::Convert, "Convert", 2, ".x");
+
+	SQGSEventSubsidyExpired.DefSQMethod(engine, &ScriptEventSubsidyExpired::GetSubsidyID, "GetSubsidyID", 1, "x");
+
+	SQGSEventSubsidyExpired.PostRegister(engine);
+}
+
+
+template <> const char *GetClassName<ScriptEventCompanyNew, ST_GS>() { return "GSEventCompanyNew"; }
+
+void SQGSEventCompanyNew_Register(Squirrel *engine)
+{
+	DefSQClass<ScriptEventCompanyNew, ST_GS> SQGSEventCompanyNew("GSEventCompanyNew");
+	SQGSEventCompanyNew.PreRegister(engine, "GSEvent");
+
+	SQGSEventCompanyNew.DefSQStaticMethod(engine, &ScriptEventCompanyNew::Convert, "Convert", 2, ".x");
+
+	SQGSEventCompanyNew.DefSQMethod(engine, &ScriptEventCompanyNew::GetCompanyID, "GetCompanyID", 1, "x");
+
+	SQGSEventCompanyNew.PostRegister(engine);
+}
+
+
+template <> const char *GetClassName<ScriptEventCompanyInTrouble, ST_GS>() { return "GSEventCompanyInTrouble"; }
+
+void SQGSEventCompanyInTrouble_Register(Squirrel *engine)
+{
+	DefSQClass<ScriptEventCompanyInTrouble, ST_GS> SQGSEventCompanyInTrouble("GSEventCompanyInTrouble");
+	SQGSEventCompanyInTrouble.PreRegister(engine, "GSEvent");
+
+	SQGSEventCompanyInTrouble.DefSQStaticMethod(engine, &ScriptEventCompanyInTrouble::Convert, "Convert", 2, ".x");
+
+	SQGSEventCompanyInTrouble.DefSQMethod(engine, &ScriptEventCompanyInTrouble::GetCompanyID, "GetCompanyID", 1, "x");
+
+	SQGSEventCompanyInTrouble.PostRegister(engine);
+}
+
+
+template <> const char *GetClassName<ScriptEventCompanyMerger, ST_GS>() { return "GSEventCompanyMerger"; }
+
+void SQGSEventCompanyMerger_Register(Squirrel *engine)
+{
+	DefSQClass<ScriptEventCompanyMerger, ST_GS> SQGSEventCompanyMerger("GSEventCompanyMerger");
+	SQGSEventCompanyMerger.PreRegister(engine, "GSEvent");
+
+	SQGSEventCompanyMerger.DefSQStaticMethod(engine, &ScriptEventCompanyMerger::Convert, "Convert", 2, ".x");
+
+	SQGSEventCompanyMerger.DefSQMethod(engine, &ScriptEventCompanyMerger::GetOldCompanyID, "GetOldCompanyID", 1, "x");
+	SQGSEventCompanyMerger.DefSQMethod(engine, &ScriptEventCompanyMerger::GetNewCompanyID, "GetNewCompanyID", 1, "x");
+
+	SQGSEventCompanyMerger.PostRegister(engine);
+}
+
+
+template <> const char *GetClassName<ScriptEventCompanyBankrupt, ST_GS>() { return "GSEventCompanyBankrupt"; }
+
+void SQGSEventCompanyBankrupt_Register(Squirrel *engine)
+{
+	DefSQClass<ScriptEventCompanyBankrupt, ST_GS> SQGSEventCompanyBankrupt("GSEventCompanyBankrupt");
+	SQGSEventCompanyBankrupt.PreRegister(engine, "GSEvent");
+
+	SQGSEventCompanyBankrupt.DefSQStaticMethod(engine, &ScriptEventCompanyBankrupt::Convert, "Convert", 2, ".x");
+
+	SQGSEventCompanyBankrupt.DefSQMethod(engine, &ScriptEventCompanyBankrupt::GetCompanyID, "GetCompanyID", 1, "x");
+
+	SQGSEventCompanyBankrupt.PostRegister(engine);
+}
+
+
+template <> const char *GetClassName<ScriptEventIndustryOpen, ST_GS>() { return "GSEventIndustryOpen"; }
+
+void SQGSEventIndustryOpen_Register(Squirrel *engine)
+{
+	DefSQClass<ScriptEventIndustryOpen, ST_GS> SQGSEventIndustryOpen("GSEventIndustryOpen");
+	SQGSEventIndustryOpen.PreRegister(engine, "GSEvent");
+
+	SQGSEventIndustryOpen.DefSQStaticMethod(engine, &ScriptEventIndustryOpen::Convert, "Convert", 2, ".x");
+
+	SQGSEventIndustryOpen.DefSQMethod(engine, &ScriptEventIndustryOpen::GetIndustryID, "GetIndustryID", 1, "x");
+
+	SQGSEventIndustryOpen.PostRegister(engine);
+}
+
+
+template <> const char *GetClassName<ScriptEventIndustryClose, ST_GS>() { return "GSEventIndustryClose"; }
+
+void SQGSEventIndustryClose_Register(Squirrel *engine)
+{
+	DefSQClass<ScriptEventIndustryClose, ST_GS> SQGSEventIndustryClose("GSEventIndustryClose");
+	SQGSEventIndustryClose.PreRegister(engine, "GSEvent");
+
+	SQGSEventIndustryClose.DefSQStaticMethod(engine, &ScriptEventIndustryClose::Convert, "Convert", 2, ".x");
+
+	SQGSEventIndustryClose.DefSQMethod(engine, &ScriptEventIndustryClose::GetIndustryID, "GetIndustryID", 1, "x");
+
+	SQGSEventIndustryClose.PostRegister(engine);
+}
+
+
+template <> const char *GetClassName<ScriptEventStationFirstVehicle, ST_GS>() { return "GSEventStationFirstVehicle"; }
+
+void SQGSEventStationFirstVehicle_Register(Squirrel *engine)
+{
+	DefSQClass<ScriptEventStationFirstVehicle, ST_GS> SQGSEventStationFirstVehicle("GSEventStationFirstVehicle");
+	SQGSEventStationFirstVehicle.PreRegister(engine, "GSEvent");
+
+	SQGSEventStationFirstVehicle.DefSQStaticMethod(engine, &ScriptEventStationFirstVehicle::Convert, "Convert", 2, ".x");
+
+	SQGSEventStationFirstVehicle.DefSQMethod(engine, &ScriptEventStationFirstVehicle::GetStationID, "GetStationID", 1, "x");
+	SQGSEventStationFirstVehicle.DefSQMethod(engine, &ScriptEventStationFirstVehicle::GetVehicleID, "GetVehicleID", 1, "x");
+
+	SQGSEventStationFirstVehicle.PostRegister(engine);
+}
+
+
+template <> const char *GetClassName<ScriptEventTownFounded, ST_GS>() { return "GSEventTownFounded"; }
+
+void SQGSEventTownFounded_Register(Squirrel *engine)
+{
+	DefSQClass<ScriptEventTownFounded, ST_GS> SQGSEventTownFounded("GSEventTownFounded");
+	SQGSEventTownFounded.PreRegister(engine, "GSEvent");
+
+	SQGSEventTownFounded.DefSQStaticMethod(engine, &ScriptEventTownFounded::Convert, "Convert", 2, ".x");
+
+	SQGSEventTownFounded.DefSQMethod(engine, &ScriptEventTownFounded::GetTownID, "GetTownID", 1, "x");
+
+	SQGSEventTownFounded.PostRegister(engine);
+}
--- a/src/script/api/script_event_types.hpp
+++ b/src/script/api/script_event_types.hpp
@@ -18,7 +18,7 @@
 /**
  * Event Vehicle Crash, indicating a vehicle of yours is crashed.
  *  It contains the crash site, the crashed vehicle and the reason for the crash.
- * @api ai
+ * @api ai game
  */
 class ScriptEventVehicleCrashed : public ScriptEvent {
 public:
@@ -79,7 +79,7 @@
 
 /**
  * Event Subsidy Offered, indicating someone offered a subsidy.
- * @api ai
+ * @api ai game
  */
 class ScriptEventSubsidyOffer : public ScriptEvent {
 public:
@@ -110,7 +110,7 @@
 
 /**
  * Event Subsidy Offer Expired, indicating a subsidy will no longer be awarded.
- * @api ai
+ * @api ai game
  */
 class ScriptEventSubsidyOfferExpired : public ScriptEvent {
 public:
@@ -141,7 +141,7 @@
 
 /**
  * Event Subidy Awarded, indicating a subsidy is awarded to some company.
- * @api ai
+ * @api ai game
  */
 class ScriptEventSubsidyAwarded : public ScriptEvent {
 public:
@@ -172,7 +172,7 @@
 
 /**
  * Event Subsidy Expired, indicating a route that was once subsidized no longer is.
- * @api ai
+ * @api ai game
  */
 class ScriptEventSubsidyExpired : public ScriptEvent {
 public:
@@ -294,7 +294,7 @@
 
 /**
  * Event Company New, indicating a new company has been created.
- * @api ai
+ * @api ai game
  */
 class ScriptEventCompanyNew : public ScriptEvent {
 public:
@@ -326,7 +326,7 @@
 /**
  * Event Company In Trouble, indicating a company is in trouble and might go
  *  bankrupt soon.
- * @api ai
+ * @api ai game
  */
 class ScriptEventCompanyInTrouble : public ScriptEvent {
 public:
@@ -405,7 +405,7 @@
 /**
  * Event Company Merger, indicating a company has been bought by another
  *  company.
- * @api ai
+ * @api ai game
  */
 class ScriptEventCompanyMerger : public ScriptEvent {
 public:
@@ -448,7 +448,7 @@
 
 /**
  * Event Company Bankrupt, indicating a company has gone bankrupt.
- * @api ai
+ * @api ai game
  */
 class ScriptEventCompanyBankrupt : public ScriptEvent {
 public:
@@ -572,7 +572,7 @@
 
 /**
  * Event Industry Open, indicating a new industry has been created.
- * @api ai
+ * @api ai game
  */
 class ScriptEventIndustryOpen : public ScriptEvent {
 public:
@@ -603,7 +603,7 @@
 
 /**
  * Event Industry Close, indicating an industry is going to be closed.
- * @api ai
+ * @api ai game
  */
 class ScriptEventIndustryClose : public ScriptEvent {
 public:
@@ -665,7 +665,7 @@
 
 /**
  * Event Station First Vehicle, indicating a station has been visited by a vehicle for the first time.
- * @api ai
+ * @api ai game
  */
 class ScriptEventStationFirstVehicle : public ScriptEvent {
 public:
@@ -767,7 +767,7 @@
 
 /**
  * Event Town Founded, indicating a new town has been created.
- * @api ai
+ * @api ai game
  */
 class ScriptEventTownFounded : public ScriptEvent {
 public:
--- a/src/subsidy.cpp
+++ b/src/subsidy.cpp
@@ -23,6 +23,7 @@
 #include "subsidy_func.h"
 #include "core/pool_func.hpp"
 #include "core/random_func.hpp"
+#include "game/game.hpp"
 
 #include "table/strings.h"
 
@@ -58,6 +59,7 @@
 		cn
 	);
 	AI::BroadcastNewEvent(new ScriptEventSubsidyAwarded(this->index));
+	Game::NewEvent(new ScriptEventSubsidyAwarded(this->index));
 
 	InvalidateWindowData(WC_SUBSIDIES_LIST, 0);
 }
@@ -202,6 +204,7 @@
 	SetPartOfSubsidyFlag(s->src_type, s->src, POS_SRC);
 	SetPartOfSubsidyFlag(s->dst_type, s->dst, POS_DST);
 	AI::BroadcastNewEvent(new ScriptEventSubsidyOffer(s->index));
+	Game::NewEvent(new ScriptEventSubsidyOffer(s->index));
 }
 
 
@@ -375,12 +378,14 @@
 				Pair reftype = SetupSubsidyDecodeParam(s, true);
 				AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NS_SUBSIDIES, (NewsReferenceType)reftype.a, s->src, (NewsReferenceType)reftype.b, s->dst);
 				AI::BroadcastNewEvent(new ScriptEventSubsidyOfferExpired(s->index));
+				Game::NewEvent(new ScriptEventSubsidyOfferExpired(s->index));
 			} else {
 				if (s->awarded == _local_company) {
 					Pair reftype = SetupSubsidyDecodeParam(s, true);
 					AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NS_SUBSIDIES, (NewsReferenceType)reftype.a, s->src, (NewsReferenceType)reftype.b, s->dst);
 				}
 				AI::BroadcastNewEvent(new ScriptEventSubsidyExpired(s->index));
+				Game::NewEvent(new ScriptEventSubsidyExpired(s->index));
 			}
 			delete s;
 			modified = true;
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -47,6 +47,7 @@
 #include "object_map.h"
 #include "object_base.h"
 #include "ai/ai.hpp"
+#include "game/game.hpp"
 
 #include "table/strings.h"
 #include "table/town_land.h"
@@ -1698,6 +1699,7 @@
 
 			AddNewsItem(STR_NEWS_NEW_TOWN, NS_INDUSTRY_OPEN, NR_TILE, tile, NR_NONE, UINT32_MAX, cn);
 			AI::BroadcastNewEvent(new ScriptEventTownFounded(t->index));
+			Game::NewEvent(new ScriptEventTownFounded(t->index));
 		}
 	}
 	return cost;
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -27,6 +27,7 @@
 #include "vehicle_func.h"
 #include "sound_func.h"
 #include "ai/ai.hpp"
+#include "game/game.hpp"
 #include "newgrf_station.h"
 #include "effectvehicle_func.h"
 #include "gamelog.h"
@@ -2714,6 +2715,7 @@
 			st->index
 		);
 		AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
+		Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
 	}
 
 	v->force_proceed = TFP_NONE;
@@ -2840,6 +2842,7 @@
 	if (!(v->vehstatus & VS_CRASHED)) {
 		num = v->Crash();
 		AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_TRAIN));
+		Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_TRAIN));
 	}
 
 	/* Try to re-reserve track under already crashed train too.
--- a/src/water_cmd.cpp
+++ b/src/water_cmd.cpp
@@ -32,6 +32,7 @@
 #include "tunnelbridge_map.h"
 #include "station_base.h"
 #include "ai/ai.hpp"
+#include "game/game.hpp"
 #include "core/random_func.hpp"
 #include "core/backup_type.hpp"
 #include "date_func.h"
@@ -910,6 +911,7 @@
 	uint pass = v->Crash(true);
 
 	AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED));
+	Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED));
 	SetDParam(0, pass);
 	AddVehicleNewsItem(STR_NEWS_DISASTER_FLOOD_VEHICLE, NS_ACCIDENT, v->index);
 	CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);