mirror of https://github.com/OpenTTD/OpenTTD
(svn r16121) [0.7] -Backport from trunk:
- Add: [NoAI] UseAsRandomAI as function in info.nut. When an AI returns false, it will never be chosen as random AI (r16113) - Fix: [NoAI] Make sure AIOrder::GetDestination always returns a tile belonging to the station (16109) - Fix: [NoAI] When giving an aircraft a goto-hangar order do not let it be a normal goto-station order (r16108) - Add: [NoAI] AIOF_STOP_IN_DEPOT to the orderflags in AIOrder to allow stop-in-depot orders (r16107) - Fix: [NoAI] AIOrder::SetOrderFlags always removed "Service if needed" from goto-depot orders (r16106) - Add: [NoAI] GetURL() as possible function to info.nut. If AIs implement it, that url is shown when the AI crashes and also in the AI selection window [FS#2808] (r16093) - Change: [NoAI] Reverse the order of the lines in the AI debug window [FS#2778] (r16091) - Fix: [NoAI] AIDebug window profiled the blitters by invalidating itself unconditionally on repaint. OTOH it was not invalidated in other cases when needed (r16094) - Fix: [NoAI] MOF_COND_DESTINATION was not accepted by CmdModifyOrder() (r16063)release/0.7
parent
f7cc97fe5c
commit
28e7981a5b
|
@ -103,6 +103,11 @@ struct AIListWindow : public Window {
|
||||||
sprintf(buf, "%d", selected_info->GetVersion());
|
sprintf(buf, "%d", selected_info->GetVersion());
|
||||||
DoDrawStringTruncated(buf, x + 5, y, TC_BLACK, this->width - x - 8);
|
DoDrawStringTruncated(buf, x + 5, y, TC_BLACK, this->width - x - 8);
|
||||||
y += 13;
|
y += 13;
|
||||||
|
if (selected_info->GetURL() != NULL) {
|
||||||
|
SetDParamStr(0, selected_info->GetURL());
|
||||||
|
DrawString(4, y, STR_AI_URL, TC_BLACK);
|
||||||
|
y += 13;
|
||||||
|
}
|
||||||
SetDParamStr(0, selected_info->GetDescription());
|
SetDParamStr(0, selected_info->GetDescription());
|
||||||
DrawStringMultiLine(4, y, STR_JUST_RAW_STRING, this->width - 8, this->widget[AIL_WIDGET_INFO_BG].bottom - y);
|
DrawStringMultiLine(4, y, STR_JUST_RAW_STRING, this->width - 8, this->widget[AIL_WIDGET_INFO_BG].bottom - y);
|
||||||
}
|
}
|
||||||
|
@ -575,6 +580,8 @@ struct AIDebugWindow : public Window {
|
||||||
|
|
||||||
static CompanyID ai_debug_company;
|
static CompanyID ai_debug_company;
|
||||||
int redraw_timer;
|
int redraw_timer;
|
||||||
|
int last_vscroll_pos;
|
||||||
|
bool autoscroll;
|
||||||
|
|
||||||
AIDebugWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number)
|
AIDebugWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number)
|
||||||
{
|
{
|
||||||
|
@ -587,6 +594,8 @@ struct AIDebugWindow : public Window {
|
||||||
this->vscroll.cap = 14;
|
this->vscroll.cap = 14;
|
||||||
this->vscroll.pos = 0;
|
this->vscroll.pos = 0;
|
||||||
this->resize.step_height = 12;
|
this->resize.step_height = 12;
|
||||||
|
this->last_vscroll_pos = 0;
|
||||||
|
this->autoscroll = true;
|
||||||
|
|
||||||
if (ai_debug_company != INVALID_COMPANY) this->LowerWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
|
if (ai_debug_company != INVALID_COMPANY) this->LowerWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
|
||||||
|
|
||||||
|
@ -664,13 +673,35 @@ struct AIDebugWindow : public Window {
|
||||||
AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
|
AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
|
||||||
_current_company = old_company;
|
_current_company = old_company;
|
||||||
|
|
||||||
SetVScrollCount(this, (log == NULL) ? 0 : log->used);
|
int scroll_count = (log == NULL) ? 0 : log->used;
|
||||||
this->InvalidateWidget(AID_WIDGET_SCROLLBAR);
|
if (this->vscroll.count != scroll_count) {
|
||||||
|
SetVScrollCount(this, scroll_count);
|
||||||
|
|
||||||
|
/* We need a repaint */
|
||||||
|
this->InvalidateWidget(AID_WIDGET_SCROLLBAR);
|
||||||
|
}
|
||||||
|
|
||||||
if (log == NULL) return;
|
if (log == NULL) return;
|
||||||
|
|
||||||
|
/* Detect when the user scrolls the window. Enable autoscroll when the
|
||||||
|
* bottom-most line becomes visible. */
|
||||||
|
if (this->last_vscroll_pos != this->vscroll.pos) {
|
||||||
|
this->autoscroll = this->vscroll.pos >= log->used - this->vscroll.cap;
|
||||||
|
}
|
||||||
|
if (this->autoscroll) {
|
||||||
|
int scroll_pos = max(0, log->used - this->vscroll.cap);
|
||||||
|
if (scroll_pos != this->vscroll.pos) {
|
||||||
|
this->vscroll.pos = scroll_pos;
|
||||||
|
|
||||||
|
/* We need a repaint */
|
||||||
|
this->InvalidateWidget(AID_WIDGET_SCROLLBAR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last_vscroll_pos = this->vscroll.pos;
|
||||||
|
|
||||||
int y = 6;
|
int y = 6;
|
||||||
for (int i = this->vscroll.pos; i < (this->vscroll.cap + this->vscroll.pos); i++) {
|
for (int i = this->vscroll.pos; i < (this->vscroll.cap + this->vscroll.pos) && i < log->used; i++) {
|
||||||
uint pos = (log->count + log->pos - i) % log->count;
|
uint pos = (i + log->pos + 1 - log->used + log->count) % log->count;
|
||||||
if (log->lines[pos] == NULL) break;
|
if (log->lines[pos] == NULL) break;
|
||||||
|
|
||||||
TextColour colour;
|
TextColour colour;
|
||||||
|
@ -693,6 +724,8 @@ struct AIDebugWindow : public Window {
|
||||||
this->RaiseWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
|
this->RaiseWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
|
||||||
ai_debug_company = show_ai;
|
ai_debug_company = show_ai;
|
||||||
this->LowerWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
|
this->LowerWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
|
||||||
|
this->autoscroll = true;
|
||||||
|
this->last_vscroll_pos = this->vscroll.pos;
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,6 +759,7 @@ struct AIDebugWindow : public Window {
|
||||||
virtual void OnResize(Point new_size, Point delta)
|
virtual void OnResize(Point new_size, Point delta)
|
||||||
{
|
{
|
||||||
this->vscroll.cap += delta.y / (int)this->resize.step_height;
|
this->vscroll.cap += delta.y / (int)this->resize.step_height;
|
||||||
|
SetVScrollCount(this, this->vscroll.count); // vscroll.pos should be in a valid range
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ AIFileInfo::~AIFileInfo()
|
||||||
free((void *)this->description);
|
free((void *)this->description);
|
||||||
free((void *)this->date);
|
free((void *)this->date);
|
||||||
free((void *)this->instance_name);
|
free((void *)this->instance_name);
|
||||||
|
free((void *)this->url);
|
||||||
free(this->main_script);
|
free(this->main_script);
|
||||||
free(this->SQ_instance);
|
free(this->SQ_instance);
|
||||||
}
|
}
|
||||||
|
@ -98,6 +99,11 @@ bool AIFileInfo::CheckMethod(const char *name) const
|
||||||
if (!info->engine->CallIntegerMethod(*info->SQ_instance, "GetVersion", &info->version)) return SQ_ERROR;
|
if (!info->engine->CallIntegerMethod(*info->SQ_instance, "GetVersion", &info->version)) return SQ_ERROR;
|
||||||
if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "CreateInstance", &info->instance_name)) return SQ_ERROR;
|
if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "CreateInstance", &info->instance_name)) return SQ_ERROR;
|
||||||
|
|
||||||
|
/* The GetURL function is optional. */
|
||||||
|
if (info->engine->MethodExists(*info->SQ_instance, "GetURL")) {
|
||||||
|
if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetURL", &info->url)) return SQ_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +131,12 @@ bool AIFileInfo::CheckMethod(const char *name) const
|
||||||
} else {
|
} else {
|
||||||
info->min_loadable_version = info->GetVersion();
|
info->min_loadable_version = info->GetVersion();
|
||||||
}
|
}
|
||||||
|
/* When there is an UseAsRandomAI function, call it. */
|
||||||
|
if (info->engine->MethodExists(*info->SQ_instance, "UseAsRandomAI")) {
|
||||||
|
if (!info->engine->CallBoolMethod(*info->SQ_instance, "UseAsRandomAI", &info->use_as_random)) return SQ_ERROR;
|
||||||
|
} else {
|
||||||
|
info->use_as_random = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */
|
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */
|
||||||
sq_setinstanceup(vm, 2, NULL);
|
sq_setinstanceup(vm, 2, NULL);
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
friend class AIInfo;
|
friend class AIInfo;
|
||||||
friend class AILibrary;
|
friend class AILibrary;
|
||||||
|
|
||||||
AIFileInfo() : SQ_instance(NULL), main_script(NULL), author(NULL), name(NULL), short_name(NULL), description(NULL), date(NULL), instance_name(NULL) {};
|
AIFileInfo() : SQ_instance(NULL), main_script(NULL), author(NULL), name(NULL), short_name(NULL), description(NULL), date(NULL), instance_name(NULL), url(NULL) {};
|
||||||
~AIFileInfo();
|
~AIFileInfo();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,6 +84,11 @@ public:
|
||||||
*/
|
*/
|
||||||
const char *GetInstanceName() const { return this->instance_name; }
|
const char *GetInstanceName() const { return this->instance_name; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the website for this script.
|
||||||
|
*/
|
||||||
|
const char *GetURL() const { return this->url; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the filename of the main.nut script.
|
* Get the filename of the main.nut script.
|
||||||
*/
|
*/
|
||||||
|
@ -111,6 +116,7 @@ private:
|
||||||
const char *date;
|
const char *date;
|
||||||
const char *instance_name;
|
const char *instance_name;
|
||||||
int version;
|
int version;
|
||||||
|
const char *url;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AIInfo : public AIFileInfo {
|
class AIInfo : public AIFileInfo {
|
||||||
|
@ -155,9 +161,15 @@ public:
|
||||||
*/
|
*/
|
||||||
int GetSettingDefaultValue(const char *name) const;
|
int GetSettingDefaultValue(const char *name) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this AI as a random AI.
|
||||||
|
*/
|
||||||
|
bool UseAsRandomAI() const { return this->use_as_random; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AIConfigItemList config_list;
|
AIConfigItemList config_list;
|
||||||
int min_loadable_version;
|
int min_loadable_version;
|
||||||
|
bool use_as_random;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AILibrary : public AIFileInfo {
|
class AILibrary : public AIFileInfo {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#define DEFINE_SCRIPT_FILES
|
#define DEFINE_SCRIPT_FILES
|
||||||
|
|
||||||
#include "ai_info.hpp"
|
#include "ai_info.hpp"
|
||||||
|
#include "ai_config.hpp"
|
||||||
#include "ai_storage.hpp"
|
#include "ai_storage.hpp"
|
||||||
#include "ai_instance.hpp"
|
#include "ai_instance.hpp"
|
||||||
#include "ai_gui.hpp"
|
#include "ai_gui.hpp"
|
||||||
|
@ -258,6 +259,12 @@ void AIInstance::Died()
|
||||||
if (strcmp(GetCompany(_current_company)->ai_info->GetMainScript(), "%_dummy") != 0) {
|
if (strcmp(GetCompany(_current_company)->ai_info->GetMainScript(), "%_dummy") != 0) {
|
||||||
ShowErrorMessage(INVALID_STRING_ID, STR_AI_PLEASE_REPORT_CRASH, 0, 0);
|
ShowErrorMessage(INVALID_STRING_ID, STR_AI_PLEASE_REPORT_CRASH, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AIInfo *info = AIConfig::GetConfig(_current_company)->GetInfo();
|
||||||
|
if (info->GetURL() != NULL) {
|
||||||
|
AILog::Info("Please report the error to the following URL:");
|
||||||
|
AILog::Info(info->GetURL());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AIInstance::GameLoop()
|
void AIInstance::GameLoop()
|
||||||
|
|
|
@ -345,20 +345,31 @@ void AIScanner::RegisterAI(AIInfo *info)
|
||||||
|
|
||||||
AIInfo *AIScanner::SelectRandomAI()
|
AIInfo *AIScanner::SelectRandomAI()
|
||||||
{
|
{
|
||||||
if (this->info_single_list.size() == 0) {
|
uint num_random_ais = 0;
|
||||||
|
for (AIInfoList::iterator it = this->info_single_list.begin(); it != this->info_single_list.end(); it++) {
|
||||||
|
if (it->second->UseAsRandomAI()) num_random_ais++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_random_ais == 0) {
|
||||||
DEBUG(ai, 0, "No suitable AI found, loading 'dummy' AI.");
|
DEBUG(ai, 0, "No suitable AI found, loading 'dummy' AI.");
|
||||||
return this->info_dummy;
|
return this->info_dummy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find a random AI */
|
/* Find a random AI */
|
||||||
uint pos;
|
uint pos;
|
||||||
if (_networking) pos = InteractiveRandomRange((uint16)this->info_single_list.size());
|
if (_networking) {
|
||||||
else pos = RandomRange((uint16)this->info_single_list.size());
|
pos = InteractiveRandomRange(num_random_ais);
|
||||||
|
} else {
|
||||||
|
pos = RandomRange(num_random_ais);
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the Nth item from the array */
|
/* Find the Nth item from the array */
|
||||||
AIInfoList::iterator it = this->info_single_list.begin();
|
AIInfoList::iterator it = this->info_single_list.begin();
|
||||||
for (; pos > 0; pos--) it++;
|
while (!it->second->UseAsRandomAI()) it++;
|
||||||
AIInfoList::iterator first_it = it;
|
for (; pos > 0; pos--) {
|
||||||
|
it++;
|
||||||
|
while (!it->second->UseAsRandomAI()) it++;
|
||||||
|
}
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
log->lines = CallocT<char *>(80);
|
log->lines = CallocT<char *>(80);
|
||||||
log->type = CallocT<AILog::AILogType>(80);
|
log->type = CallocT<AILog::AILogType>(80);
|
||||||
log->count = 80;
|
log->count = 80;
|
||||||
log->pos = log->count;
|
log->pos = log->count - 1;
|
||||||
log->used = 0;
|
log->used = 0;
|
||||||
}
|
}
|
||||||
LogData *log = (LogData *)AIObject::GetLogPointer();
|
LogData *log = (LogData *)AIObject::GetLogPointer();
|
||||||
|
|
|
@ -23,7 +23,10 @@ static OrderType GetOrderTypeByTile(TileIndex t)
|
||||||
|
|
||||||
switch (::GetTileType(t)) {
|
switch (::GetTileType(t)) {
|
||||||
default: break;
|
default: break;
|
||||||
case MP_STATION: return OT_GOTO_STATION; break;
|
case MP_STATION:
|
||||||
|
if (IsHangar(t)) return OT_GOTO_DEPOT;
|
||||||
|
return OT_GOTO_STATION;
|
||||||
|
break;
|
||||||
case MP_WATER: if (::IsShipDepot(t)) return OT_GOTO_DEPOT; break;
|
case MP_WATER: if (::IsShipDepot(t)) return OT_GOTO_DEPOT; break;
|
||||||
case MP_ROAD: if (::GetRoadTileType(t) == ROAD_TILE_DEPOT) return OT_GOTO_DEPOT; break;
|
case MP_ROAD: if (::GetRoadTileType(t) == ROAD_TILE_DEPOT) return OT_GOTO_DEPOT; break;
|
||||||
case MP_RAILWAY:
|
case MP_RAILWAY:
|
||||||
|
@ -74,7 +77,10 @@ static OrderType GetOrderTypeByTile(TileIndex t)
|
||||||
(((order_flags & AIOF_NO_UNLOAD) == 0) || ((order_flags & AIOF_NO_LOAD) == 0)) &&
|
(((order_flags & AIOF_NO_UNLOAD) == 0) || ((order_flags & AIOF_NO_LOAD) == 0)) &&
|
||||||
(((order_flags & AIOF_FULL_LOAD_ANY) == 0) || ((order_flags & AIOF_NO_LOAD) == 0));
|
(((order_flags & AIOF_FULL_LOAD_ANY) == 0) || ((order_flags & AIOF_NO_LOAD) == 0));
|
||||||
|
|
||||||
case OT_GOTO_DEPOT: return (order_flags & ~(AIOF_NON_STOP_FLAGS | AIOF_SERVICE_IF_NEEDED)) == 0;
|
case OT_GOTO_DEPOT:
|
||||||
|
return ((order_flags & ~(AIOF_NON_STOP_FLAGS | AIOF_DEPOT_FLAGS)) == 0) &&
|
||||||
|
(((order_flags & AIOF_SERVICE_IF_NEEDED) == 0) || ((order_flags & AIOF_STOP_IN_DEPOT) == 0));
|
||||||
|
|
||||||
case OT_GOTO_WAYPOINT: return (order_flags & ~(AIOF_NON_STOP_FLAGS)) == 0;
|
case OT_GOTO_WAYPOINT: return (order_flags & ~(AIOF_NON_STOP_FLAGS)) == 0;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
|
@ -118,11 +124,36 @@ static OrderType GetOrderTypeByTile(TileIndex t)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (order->GetType()) {
|
switch (order->GetType()) {
|
||||||
case OT_GOTO_DEPOT:
|
case OT_GOTO_DEPOT: {
|
||||||
if (v->type != VEH_AIRCRAFT) return ::GetDepot(order->GetDestination())->xy;
|
if (v->type != VEH_AIRCRAFT) return ::GetDepot(order->GetDestination())->xy;
|
||||||
/* FALL THROUGH: aircraft's hangars are referenced by StationID, not DepotID */
|
/* Aircraft's hangars are referenced by StationID, not DepotID */
|
||||||
|
const Station *st = ::GetStation(order->GetDestination());
|
||||||
|
const AirportFTAClass *airport = st->Airport();
|
||||||
|
if (airport == NULL || airport->nof_depots == 0) return INVALID_TILE;
|
||||||
|
return st->airport_tile + ::ToTileIndexDiff(st->Airport()->airport_depots[0]);
|
||||||
|
}
|
||||||
|
|
||||||
case OT_GOTO_STATION: return ::GetStation(order->GetDestination())->xy;
|
case OT_GOTO_STATION: {
|
||||||
|
const Station *st = ::GetStation(order->GetDestination());
|
||||||
|
if (st->train_tile != INVALID_TILE) {
|
||||||
|
for (uint i = 0; i < st->trainst_w; i++) {
|
||||||
|
TileIndex t = st->train_tile + TileDiffXY(i, 0);
|
||||||
|
if (st->TileBelongsToRailStation(t)) return t;
|
||||||
|
}
|
||||||
|
} else if (st->dock_tile != INVALID_TILE) {
|
||||||
|
return st->dock_tile;
|
||||||
|
} else if (st->bus_stops != NULL) {
|
||||||
|
return st->bus_stops->xy;
|
||||||
|
} else if (st->truck_stops != NULL) {
|
||||||
|
return st->truck_stops->xy;
|
||||||
|
} else if (st->airport_tile != INVALID_TILE) {
|
||||||
|
const AirportFTAClass *fta = st->Airport();
|
||||||
|
BEGIN_TILE_LOOP(tile, fta->size_x, fta->size_y, st->airport_tile) {
|
||||||
|
if (!::IsHangar(tile)) return tile;
|
||||||
|
} END_TILE_LOOP(tile, fta->size_x, fta->size_y, st->airport_tile)
|
||||||
|
}
|
||||||
|
return INVALID_TILE;
|
||||||
|
}
|
||||||
case OT_GOTO_WAYPOINT: return ::GetWaypoint(order->GetDestination())->xy;
|
case OT_GOTO_WAYPOINT: return ::GetWaypoint(order->GetDestination())->xy;
|
||||||
default: return INVALID_TILE;
|
default: return INVALID_TILE;
|
||||||
}
|
}
|
||||||
|
@ -145,6 +176,7 @@ static OrderType GetOrderTypeByTile(TileIndex t)
|
||||||
switch (order->GetType()) {
|
switch (order->GetType()) {
|
||||||
case OT_GOTO_DEPOT:
|
case OT_GOTO_DEPOT:
|
||||||
if (order->GetDepotOrderType() & ODTFB_SERVICE) order_flags |= AIOF_SERVICE_IF_NEEDED;
|
if (order->GetDepotOrderType() & ODTFB_SERVICE) order_flags |= AIOF_SERVICE_IF_NEEDED;
|
||||||
|
if (order->GetDepotActionType() & ODATFB_HALT) order_flags |= AIOF_STOP_IN_DEPOT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OT_GOTO_STATION:
|
case OT_GOTO_STATION:
|
||||||
|
@ -260,9 +292,20 @@ static OrderType GetOrderTypeByTile(TileIndex t)
|
||||||
|
|
||||||
Order order;
|
Order order;
|
||||||
switch (::GetOrderTypeByTile(destination)) {
|
switch (::GetOrderTypeByTile(destination)) {
|
||||||
case OT_GOTO_DEPOT:
|
case OT_GOTO_DEPOT: {
|
||||||
order.MakeGoToDepot(::GetDepotByTile(destination)->index, (OrderDepotTypeFlags)(ODTFB_PART_OF_ORDERS | ((order_flags & AIOF_SERVICE_IF_NEEDED) ? ODTFB_SERVICE : 0)));
|
OrderDepotTypeFlags odtf = (OrderDepotTypeFlags)(ODTFB_PART_OF_ORDERS | ((order_flags & AIOF_SERVICE_IF_NEEDED) ? ODTFB_SERVICE : 0));
|
||||||
|
OrderDepotActionFlags odaf = (OrderDepotActionFlags)(ODATF_SERVICE_ONLY | ((order_flags & AIOF_STOP_IN_DEPOT) ? ODATFB_HALT : 0));
|
||||||
|
/* Check explicitly if the order is to a station (for aircraft) or
|
||||||
|
* to a depot (other vehicle types). */
|
||||||
|
if (::GetVehicle(vehicle_id)->type == VEH_AIRCRAFT) {
|
||||||
|
if (!::IsTileType(destination, MP_STATION)) return false;
|
||||||
|
order.MakeGoToDepot(::GetStationIndex(destination), odtf, odaf);
|
||||||
|
} else {
|
||||||
|
if (::IsTileType(destination, MP_STATION)) return false;
|
||||||
|
order.MakeGoToDepot(::GetDepotByTile(destination)->index, odtf, odaf);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case OT_GOTO_STATION:
|
case OT_GOTO_STATION:
|
||||||
order.MakeGoToStation(::GetStationIndex(destination));
|
order.MakeGoToStation(::GetStationIndex(destination));
|
||||||
|
@ -356,8 +399,11 @@ static void _DoCommandReturnSetOrderFlags(class AIInstance *instance)
|
||||||
|
|
||||||
switch (order->GetType()) {
|
switch (order->GetType()) {
|
||||||
case OT_GOTO_DEPOT:
|
case OT_GOTO_DEPOT:
|
||||||
if ((current & AIOF_SERVICE_IF_NEEDED) != (order_flags & AIOF_SERVICE_IF_NEEDED)) {
|
if ((current & AIOF_DEPOT_FLAGS) != (order_flags & AIOF_DEPOT_FLAGS)) {
|
||||||
return AIObject::DoCommand(0, vehicle_id | (order_position << 16), MOF_DEPOT_ACTION, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
|
uint data = DA_ALWAYS_GO;
|
||||||
|
if (order_flags & AIOF_SERVICE_IF_NEEDED) data = DA_SERVICE;
|
||||||
|
if (order_flags & AIOF_STOP_IN_DEPOT) data = DA_STOP;
|
||||||
|
return AIObject::DoCommand(0, vehicle_id | (order_position << 16), (data << 4) | MOF_DEPOT_ACTION, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,8 @@ public:
|
||||||
|
|
||||||
/** Service the vehicle when needed, otherwise skip this order; only for depots. */
|
/** Service the vehicle when needed, otherwise skip this order; only for depots. */
|
||||||
AIOF_SERVICE_IF_NEEDED = 1 << 2,
|
AIOF_SERVICE_IF_NEEDED = 1 << 2,
|
||||||
|
/** Stop in the depot instead of only go there for servicing; only for depots. */
|
||||||
|
AIOF_STOP_IN_DEPOT = 1 << 3,
|
||||||
|
|
||||||
/** All flags related to non-stop settings. */
|
/** All flags related to non-stop settings. */
|
||||||
AIOF_NON_STOP_FLAGS = AIOF_NON_STOP_INTERMEDIATE | AIOF_NON_STOP_DESTINATION,
|
AIOF_NON_STOP_FLAGS = AIOF_NON_STOP_INTERMEDIATE | AIOF_NON_STOP_DESTINATION,
|
||||||
|
@ -64,6 +66,8 @@ public:
|
||||||
AIOF_UNLOAD_FLAGS = AIOF_TRANSFER | AIOF_UNLOAD | AIOF_NO_UNLOAD,
|
AIOF_UNLOAD_FLAGS = AIOF_TRANSFER | AIOF_UNLOAD | AIOF_NO_UNLOAD,
|
||||||
/** All flags related to loading. */
|
/** All flags related to loading. */
|
||||||
AIOF_LOAD_FLAGS = AIOF_FULL_LOAD | AIOF_FULL_LOAD_ANY | AIOF_NO_LOAD,
|
AIOF_LOAD_FLAGS = AIOF_FULL_LOAD | AIOF_FULL_LOAD_ANY | AIOF_NO_LOAD,
|
||||||
|
/** All flags related to depots. */
|
||||||
|
AIOF_DEPOT_FLAGS = AIOF_SERVICE_IF_NEEDED | AIOF_STOP_IN_DEPOT,
|
||||||
|
|
||||||
/** For marking invalid order flags */
|
/** For marking invalid order flags */
|
||||||
AIOF_INVALID = 0xFFFF,
|
AIOF_INVALID = 0xFFFF,
|
||||||
|
|
|
@ -42,9 +42,11 @@ void SQAIOrder_Register(Squirrel *engine) {
|
||||||
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_FULL_LOAD_ANY, "AIOF_FULL_LOAD_ANY");
|
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_FULL_LOAD_ANY, "AIOF_FULL_LOAD_ANY");
|
||||||
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NO_LOAD, "AIOF_NO_LOAD");
|
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NO_LOAD, "AIOF_NO_LOAD");
|
||||||
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_SERVICE_IF_NEEDED, "AIOF_SERVICE_IF_NEEDED");
|
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_SERVICE_IF_NEEDED, "AIOF_SERVICE_IF_NEEDED");
|
||||||
|
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_STOP_IN_DEPOT, "AIOF_STOP_IN_DEPOT");
|
||||||
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NON_STOP_FLAGS, "AIOF_NON_STOP_FLAGS");
|
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NON_STOP_FLAGS, "AIOF_NON_STOP_FLAGS");
|
||||||
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_UNLOAD_FLAGS, "AIOF_UNLOAD_FLAGS");
|
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_UNLOAD_FLAGS, "AIOF_UNLOAD_FLAGS");
|
||||||
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_LOAD_FLAGS, "AIOF_LOAD_FLAGS");
|
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_LOAD_FLAGS, "AIOF_LOAD_FLAGS");
|
||||||
|
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_DEPOT_FLAGS, "AIOF_DEPOT_FLAGS");
|
||||||
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_INVALID, "AIOF_INVALID");
|
SQAIOrder.DefSQConst(engine, AIOrder::AIOF_INVALID, "AIOF_INVALID");
|
||||||
SQAIOrder.DefSQConst(engine, AIOrder::OC_LOAD_PERCENTAGE, "OC_LOAD_PERCENTAGE");
|
SQAIOrder.DefSQConst(engine, AIOrder::OC_LOAD_PERCENTAGE, "OC_LOAD_PERCENTAGE");
|
||||||
SQAIOrder.DefSQConst(engine, AIOrder::OC_RELIABILITY, "OC_RELIABILITY");
|
SQAIOrder.DefSQConst(engine, AIOrder::OC_RELIABILITY, "OC_RELIABILITY");
|
||||||
|
|
|
@ -3585,6 +3585,7 @@ STR_AI_RANDOM_AI :Random AI
|
||||||
STR_AI_SETTINGS_CAPTION :{WHITE}AI Parameters
|
STR_AI_SETTINGS_CAPTION :{WHITE}AI Parameters
|
||||||
STR_AI_AUTHOR :Author:
|
STR_AI_AUTHOR :Author:
|
||||||
STR_AI_VERSION :Version:
|
STR_AI_VERSION :Version:
|
||||||
|
STR_AI_URL :URL: {RAW_STRING}
|
||||||
STR_AI_PLEASE_REPORT_CRASH :{WHITE}One of the running AIs crashed. Please report this to the AI author with a screenshot of the AI Debug Window.
|
STR_AI_PLEASE_REPORT_CRASH :{WHITE}One of the running AIs crashed. Please report this to the AI author with a screenshot of the AI Debug Window.
|
||||||
########
|
########
|
||||||
|
|
||||||
|
|
|
@ -498,7 +498,8 @@ CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||||
|
|
||||||
if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN && v->type != VEH_ROAD) return CMD_ERROR;
|
if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN && v->type != VEH_ROAD) return CMD_ERROR;
|
||||||
if (new_order.GetDepotOrderType() & ~(ODTFB_PART_OF_ORDERS | ((new_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0 ? ODTFB_SERVICE : 0))) return CMD_ERROR;
|
if (new_order.GetDepotOrderType() & ~(ODTFB_PART_OF_ORDERS | ((new_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0 ? ODTFB_SERVICE : 0))) return CMD_ERROR;
|
||||||
if (new_order.GetDepotActionType() & ~ODATFB_NEAREST_DEPOT) return CMD_ERROR;
|
if (new_order.GetDepotActionType() & ~(ODATFB_HALT | ODATFB_NEAREST_DEPOT)) return CMD_ERROR;
|
||||||
|
if ((new_order.GetDepotOrderType() & ODTFB_SERVICE) && (new_order.GetDepotActionType() & ODATFB_HALT)) return CMD_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -862,7 +863,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OT_CONDITIONAL:
|
case OT_CONDITIONAL:
|
||||||
if (mof != MOF_COND_VARIABLE && mof != MOF_COND_COMPARATOR && mof != MOF_COND_VALUE) return CMD_ERROR;
|
if (mof != MOF_COND_VARIABLE && mof != MOF_COND_COMPARATOR && mof != MOF_COND_VALUE && mof != MOF_COND_DESTINATION) return CMD_ERROR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -234,6 +234,15 @@ bool Squirrel::CallIntegerMethod(HSQOBJECT instance, const char *method_name, in
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Squirrel::CallBoolMethod(HSQOBJECT instance, const char *method_name, bool *res, int suspend)
|
||||||
|
{
|
||||||
|
HSQOBJECT ret;
|
||||||
|
if (!this->CallMethod(instance, method_name, &ret, suspend)) return false;
|
||||||
|
if (ret._type != OT_BOOL) return false;
|
||||||
|
*res = ObjectToBool(&ret);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* static */ bool Squirrel::CreateClassInstanceVM(HSQUIRRELVM vm, const char *class_name, void *real_instance, HSQOBJECT *instance, SQRELEASEHOOK release_hook)
|
/* static */ bool Squirrel::CreateClassInstanceVM(HSQUIRRELVM vm, const char *class_name, void *real_instance, HSQOBJECT *instance, SQRELEASEHOOK release_hook)
|
||||||
{
|
{
|
||||||
int oldtop = sq_gettop(vm);
|
int oldtop = sq_gettop(vm);
|
||||||
|
|
|
@ -116,6 +116,7 @@ public:
|
||||||
bool CallMethod(HSQOBJECT instance, const char *method_name, int suspend = -1) { return this->CallMethod(instance, method_name, NULL, suspend); }
|
bool CallMethod(HSQOBJECT instance, const char *method_name, int suspend = -1) { return this->CallMethod(instance, method_name, NULL, suspend); }
|
||||||
bool CallStringMethodStrdup(HSQOBJECT instance, const char *method_name, const char **res, int suspend = -1);
|
bool CallStringMethodStrdup(HSQOBJECT instance, const char *method_name, const char **res, int suspend = -1);
|
||||||
bool CallIntegerMethod(HSQOBJECT instance, const char *method_name, int *res, int suspend = -1);
|
bool CallIntegerMethod(HSQOBJECT instance, const char *method_name, int *res, int suspend = -1);
|
||||||
|
bool CallBoolMethod(HSQOBJECT instance, const char *method_name, bool *res, int suspend = -1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a method exists in an instance.
|
* Check if a method exists in an instance.
|
||||||
|
@ -161,6 +162,11 @@ public:
|
||||||
*/
|
*/
|
||||||
static int ObjectToInteger(HSQOBJECT *ptr) { return sq_objtointeger(ptr); }
|
static int ObjectToInteger(HSQOBJECT *ptr) { return sq_objtointeger(ptr); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a Squirrel-object to a bool.
|
||||||
|
*/
|
||||||
|
static bool ObjectToBool(HSQOBJECT *ptr) { return sq_objtobool(ptr) == 1; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a pointer in the VM that is reachable from where ever you are in SQ.
|
* Sets a pointer in the VM that is reachable from where ever you are in SQ.
|
||||||
* Useful to keep track of the main instance.
|
* Useful to keep track of the main instance.
|
||||||
|
|
Loading…
Reference in New Issue