(svn r12838) [NoAI] -Add: added AIEventEnginePreview, which tells you when you have been chosen for testing an engine, and allows you to accept it noai
authorglx
Tue, 22 Apr 2008 17:04:06 +0000
branchnoai
changeset 10297 433b21fd002c
parent 10294 7798ae816af8
child 10299 7f1a1c0b6c86
(svn r12838) [NoAI] -Add: added AIEventEnginePreview, which tells you when you have been chosen for testing an engine, and allows you to accept it
src/ai/ai_squirrel.cpp
src/ai/api/ai_event.hpp
src/ai/api/ai_event.hpp.sq
src/ai/api/ai_event_types.cpp
src/ai/api/ai_event_types.hpp
src/ai/api/ai_event_types.hpp.sq
src/engine.cpp
--- a/src/ai/ai_squirrel.cpp	Mon Apr 21 21:15:50 2008 +0000
+++ b/src/ai/ai_squirrel.cpp	Tue Apr 22 17:04:06 2008 +0000
@@ -230,6 +230,7 @@
 	SQAIError_Register(this->engine);
 	SQAIEvent_Register(this->engine);
 	SQAIEventController_Register(this->engine);
+	SQAIEventEnginePreview_Register(this->engine);
 	SQAIEventSubsidyOffer_Register(this->engine);
 	SQAIEventTest_Register(this->engine);
 	SQAIEventVehicleCrash_Register(this->engine);
--- a/src/ai/api/ai_event.hpp	Mon Apr 21 21:15:50 2008 +0000
+++ b/src/ai/api/ai_event.hpp	Tue Apr 22 17:04:06 2008 +0000
@@ -24,6 +24,7 @@
 		AI_ET_TEST,
 		AI_ET_CRASHED_VEHICLE,
 		AI_ET_SUBSIDY_OFFER,
+		AI_ET_ENGINE_PREVIEW,
 	};
 
 	/**
--- a/src/ai/api/ai_event.hpp.sq	Mon Apr 21 21:15:50 2008 +0000
+++ b/src/ai/api/ai_event.hpp.sq	Tue Apr 22 17:04:06 2008 +0000
@@ -25,6 +25,7 @@
 	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_TEST,            "AI_ET_TEST");
 	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_CRASHED_VEHICLE, "AI_ET_CRASHED_VEHICLE");
 	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_SUBSIDY_OFFER,   "AI_ET_SUBSIDY_OFFER");
+	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_ENGINE_PREVIEW,  "AI_ET_ENGINE_PREVIEW");
 
 	SQAIEvent.DefSQStaticMethod(engine, &AIEvent::GetClassName, "GetClassName", 1, "x");
 
--- a/src/ai/api/ai_event_types.cpp	Mon Apr 21 21:15:50 2008 +0000
+++ b/src/ai/api/ai_event_types.cpp	Tue Apr 22 17:04:06 2008 +0000
@@ -3,8 +3,183 @@
 /** @file ai_event_types.cpp Implementation of all EventTypes. */
 
 #include "ai_event_types.hpp"
+#include "../../strings_func.h"
+#include "../../roadveh.h"
+#include "../../train.h"
+#include "../../ship.h"
+#include "../../aircraft.h"
+#include "../../settings_type.h"
+#include "../../articulated_vehicles.h"
+#include "table/strings.h"
 
 bool AIEventVehicleCrash::CloneCrashedVehicle(TileIndex depot)
 {
 	return false;
 }
+
+char *AIEventEnginePreview::GetName()
+{
+	static const int len = 64;
+	char *engine_name = MallocT<char>(len);
+
+	::SetDParam(0, engine);
+	::GetString(engine_name, STR_ENGINE_NAME, &engine_name[len - 1]);
+	return engine_name;
+}
+
+CargoID AIEventEnginePreview::GetCargoType()
+{
+	switch (::GetEngine(engine)->type) {
+		case VEH_ROAD: {
+			const RoadVehicleInfo *vi = ::RoadVehInfo(engine);
+			return vi->cargo_type;
+		} break;
+
+		case VEH_TRAIN: {
+			const RailVehicleInfo *vi = ::RailVehInfo(engine);
+			return vi->cargo_type;
+		} break;
+
+		case VEH_SHIP: {
+			const ShipVehicleInfo *vi = ::ShipVehInfo(engine);
+			return vi->cargo_type;
+		} break;
+
+		case VEH_AIRCRAFT: {
+			return CT_PASSENGERS;
+		} break;
+
+		default: NOT_REACHED();
+	}
+}
+
+int32 AIEventEnginePreview::GetCapacity()
+{
+	switch (::GetEngine(engine)->type) {
+		case VEH_ROAD:
+		case VEH_TRAIN: {
+			uint16 *capacities = GetCapacityOfArticulatedParts(engine, ::GetEngine(engine)->type);
+			for (CargoID c = 0; c < NUM_CARGO; c++) {
+				if (capacities[c] == 0) continue;
+				return capacities[c];
+			}
+			return -1;
+		} break;
+
+		case VEH_SHIP: {
+			const ShipVehicleInfo *vi = ::ShipVehInfo(engine);
+			return vi->capacity;
+		} break;
+
+		case VEH_AIRCRAFT: {
+			const AircraftVehicleInfo *vi = ::AircraftVehInfo(engine);
+			return vi->passenger_capacity;
+		} break;
+
+		default: NOT_REACHED();
+	}
+}
+
+int32 AIEventEnginePreview::GetMaxSpeed()
+{
+	switch (::GetEngine(engine)->type) {
+		case VEH_ROAD: {
+			const RoadVehicleInfo *vi = ::RoadVehInfo(engine);
+			/* Internal speeds are km/h * 2 */
+			return vi->max_speed / 2;
+		} break;
+
+		case VEH_TRAIN: {
+			const RailVehicleInfo *vi = ::RailVehInfo(engine);
+			return vi->max_speed;
+		} break;
+
+		case VEH_SHIP: {
+			const ShipVehicleInfo *vi = ::ShipVehInfo(engine);
+			/* Internal speeds are km/h * 2 */
+			return vi->max_speed / 2;
+		} break;
+
+		case VEH_AIRCRAFT: {
+			const AircraftVehicleInfo *vi = ::AircraftVehInfo(engine);
+			return vi->max_speed / _patches.plane_speed;
+		} break;
+
+		default: NOT_REACHED();
+	}
+}
+
+Money AIEventEnginePreview::GetPrice()
+{
+	switch (::GetEngine(engine)->type) {
+		case VEH_ROAD: {
+			const RoadVehicleInfo *vi = ::RoadVehInfo(engine);
+			return (_price.roadveh_base >> 3) * vi->base_cost >> 5;
+		} break;
+
+		case VEH_TRAIN: {
+			const RailVehicleInfo *vi = ::RailVehInfo(engine);
+			return (_price.build_railvehicle >> 3) * vi->base_cost >> 5;
+		} break;
+
+		case VEH_SHIP: {
+			const ShipVehicleInfo *vi = ::ShipVehInfo(engine);
+			return (_price.ship_base >> 3) * vi->base_cost >> 5;
+		} break;
+
+		case VEH_AIRCRAFT: {
+			const AircraftVehicleInfo *vi = ::AircraftVehInfo(engine);
+			return (_price.aircraft_base >> 3) * vi->base_cost >> 5;
+		} break;
+
+		default: NOT_REACHED();
+	}
+}
+
+Money AIEventEnginePreview::GetRunningCost()
+{
+	/* We need to create an instance in order to obtain GetRunningCost.
+	 *  This means we temporary allocate a vehicle in the pool, but
+	 *  there is no other way.. */
+	Vehicle *vehicle;
+	switch (::GetEngine(engine)->type) {
+		case VEH_ROAD: {
+			vehicle = new RoadVehicle();
+		} break;
+
+		case VEH_TRAIN: {
+			vehicle = new Train();
+		} break;
+
+		case VEH_SHIP: {
+			vehicle = new Ship();
+		} break;
+
+		case VEH_AIRCRAFT: {
+			vehicle = new Aircraft();
+		} break;
+
+		default: NOT_REACHED();
+	}
+
+	vehicle->engine_type = engine;
+	Money runningCost = vehicle->GetRunningCost();
+	delete vehicle;
+	return runningCost >> 8;
+}
+
+AIVehicle::VehicleType AIEventEnginePreview::GetVehicleType()
+{
+	switch (::GetEngine(engine)->type) {
+		case VEH_ROAD:     return AIVehicle::VEHICLE_ROAD;
+		case VEH_TRAIN:    return AIVehicle::VEHICLE_RAIL;
+		case VEH_SHIP:     return AIVehicle::VEHICLE_WATER;
+		case VEH_AIRCRAFT: return AIVehicle::VEHICLE_AIR;
+		default: NOT_REACHED();
+	}
+}
+
+bool AIEventEnginePreview::AcceptPreview()
+{
+	return AIObject::DoCommand(0, engine, 0, CMD_WANT_ENGINE_PREVIEW);
+}
--- a/src/ai/api/ai_event_types.hpp	Mon Apr 21 21:15:50 2008 +0000
+++ b/src/ai/api/ai_event_types.hpp	Tue Apr 22 17:04:06 2008 +0000
@@ -9,6 +9,7 @@
 #include "ai_event.hpp"
 #include "ai_town.hpp"
 #include "ai_industry.hpp"
+#include "ai_engine.hpp"
 
 /**
  * Event Test: a simple test event, to see if the event system is working.
@@ -167,4 +168,83 @@
 	uint32 to;
 };
 
+/**
+ * Event Engine Preview, indicating a manufacturer offer you to test a new engine.
+ *  You can get the type of engine.
+ */
+class AIEventEnginePreview : public AIEvent {
+public:
+	static const char *GetClassName() { return "AIEventEnginePreview"; }
+
+	/**
+	 * @param engine The engine offered to test.
+	 */
+	AIEventEnginePreview(EngineID engine) :
+		AIEvent(AI_ET_ENGINE_PREVIEW),
+		engine(engine)
+	{}
+
+	/**
+	 * Convert an AIEvent to the real instance.
+	 * @param instance The instance to convert.
+	 * @return The converted instance.
+	 */
+	static AIEventEnginePreview *Convert(AIEvent *instance) { return (AIEventEnginePreview *)instance; }
+
+	/**
+	 * Get the name of the offered engine.
+	 * @return The name the engine has.
+	 */
+	char *GetName();
+
+	/**
+	 * Get the cargo-type of the offered engine. In case it can transport 2 cargos, it
+	 *  returns the first.
+	 * @return The cargo-type of the engine.
+	 */
+	CargoID GetCargoType();
+
+	/**
+	 * Get the capacity of the offered engine. In case it can transport 2 cargos, it
+	 *  returns the first.
+	 * @return The capacity of the engine.
+	 */
+	int32 GetCapacity();
+
+	/**
+	 * Get the maximum speed of the offered engine.
+	 * @return The maximum speed the engine has.
+	 * @note The speed is in km/h.
+	 */
+	int32 GetMaxSpeed();
+
+	/**
+	 * Get the new cost of the offered engine.
+	 * @return The new cost the engine has.
+	 */
+	Money GetPrice();
+
+	/**
+	 * Get the running cost of the offered engine.
+	 * @return The running cost of the vehicle per year.
+	 * @note Cost is per year; divide by 364 to get per day.
+	 */
+	Money GetRunningCost();
+
+	/**
+	 * Get the type of the offered engine.
+	 * @return The type the engine has.
+	 */
+	AIVehicle::VehicleType GetVehicleType();
+
+	/**
+	 * Accept the engine preview.
+	 * @return True when the accepting succeeded.
+	 */
+	bool AcceptPreview();
+
+private:
+	EngineID engine;
+};
+
 #endif /* AI_EVENT_TYPES_HPP */
--- a/src/ai/api/ai_event_types.hpp.sq	Mon Apr 21 21:15:50 2008 +0000
+++ b/src/ai/api/ai_event_types.hpp.sq	Tue Apr 22 17:04:06 2008 +0000
@@ -74,3 +74,32 @@
 
 	SQAIEventSubsidyOffer.PostRegister(engine);
 }
+
+namespace SQConvert {
+	/* Allow AIEventEnginePreview to be used as Squirrel parameter */
+	template <> AIEventEnginePreview *GetParam(ForceType<AIEventEnginePreview *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIEventEnginePreview *)instance; }
+	template <> AIEventEnginePreview &GetParam(ForceType<AIEventEnginePreview &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventEnginePreview *)instance; }
+	template <> const AIEventEnginePreview *GetParam(ForceType<const AIEventEnginePreview *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIEventEnginePreview *)instance; }
+	template <> const AIEventEnginePreview &GetParam(ForceType<const AIEventEnginePreview &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventEnginePreview *)instance; }
+	template <> int Return<AIEventEnginePreview *>(HSQUIRRELVM vm, AIEventEnginePreview *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventEnginePreview", res, NULL, DefSQDestructorCallback<AIEventEnginePreview>); return 1; }
+}; // namespace SQConvert
+
+void SQAIEventEnginePreview_Register(Squirrel *engine) {
+	DefSQClass <AIEventEnginePreview> SQAIEventEnginePreview("AIEventEnginePreview");
+	SQAIEventEnginePreview.PreRegister(engine, "AIEvent");
+	SQAIEventEnginePreview.AddConstructor<void (AIEventEnginePreview::*)(EngineID engine), 2>(engine, "xi");
+
+	SQAIEventEnginePreview.DefSQStaticMethod(engine, &AIEventEnginePreview::GetClassName, "GetClassName", 1, "x");
+	SQAIEventEnginePreview.DefSQStaticMethod(engine, &AIEventEnginePreview::Convert,      "Convert",      2, "xx");
+
+	SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetName,        "GetName",        1, "x");
+	SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetCargoType,   "GetCargoType",   1, "x");
+	SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetCapacity,    "GetCapacity",    1, "x");
+	SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetMaxSpeed,    "GetMaxSpeed",    1, "x");
+	SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetPrice,       "GetPrice",       1, "x");
+	SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetRunningCost, "GetRunningCost", 1, "x");
+	SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetVehicleType, "GetVehicleType", 1, "x");
+	SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::AcceptPreview,  "AcceptPreview",  1, "x");
+
+	SQAIEventEnginePreview.PostRegister(engine);
+}
--- a/src/engine.cpp	Mon Apr 21 21:15:50 2008 +0000
+++ b/src/engine.cpp	Tue Apr 22 17:04:06 2008 +0000
@@ -26,6 +26,7 @@
 #include "string_func.h"
 #include "settings_type.h"
 #include "oldpool_func.h"
+#include "ai/ai.h"
 
 #include "table/strings.h"
 #include "table/engines.h"
@@ -247,14 +248,10 @@
 					continue;
 				}
 
-				if (!IsHumanPlayer(best_player)) {
-					/* XXX - TTDBUG: TTD has a bug here ???? */
-					AcceptEnginePreview(i, best_player);
-				} else {
-					e->flags |= ENGINE_OFFER_WINDOW_OPEN;
-					e->preview_wait = 20;
-					if (IsInteractivePlayer(best_player)) ShowEnginePreviewWindow(i);
-				}
+				e->flags |= ENGINE_OFFER_WINDOW_OPEN;
+				e->preview_wait = 20;
+				AI_Event(best_player, new AIEventEnginePreview(i));
+				if (IsInteractivePlayer(best_player)) ShowEnginePreviewWindow(i);
 			}
 		}
 	}