2009-01-12 18:11:45 +01:00
|
|
|
/* $Id$ */
|
|
|
|
|
2009-08-21 22:21:05 +02:00
|
|
|
/*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2011-11-30 00:07:38 +01:00
|
|
|
/** @file script_event_types.cpp Implementation of all EventTypes. */
|
2009-01-12 18:11:45 +01:00
|
|
|
|
2011-01-22 11:33:16 +01:00
|
|
|
#include "../../stdafx.h"
|
2011-11-30 00:07:38 +01:00
|
|
|
#include "script_event_types.hpp"
|
|
|
|
#include "script_vehicle.hpp"
|
2011-12-19 22:00:32 +01:00
|
|
|
#include "script_log.hpp"
|
2009-01-12 18:11:45 +01:00
|
|
|
#include "../../strings_func.h"
|
|
|
|
#include "../../settings_type.h"
|
2009-03-18 20:32:13 +01:00
|
|
|
#include "../../engine_base.h"
|
2009-01-12 18:11:45 +01:00
|
|
|
#include "../../articulated_vehicles.h"
|
2014-04-25 17:40:32 +02:00
|
|
|
#include "../../string_func.h"
|
2009-01-12 18:11:45 +01:00
|
|
|
#include "table/strings.h"
|
|
|
|
|
2014-04-23 22:13:33 +02:00
|
|
|
#include "../../safeguards.h"
|
|
|
|
|
2011-11-30 00:15:35 +01:00
|
|
|
bool ScriptEventEnginePreview::IsEngineValid() const
|
2011-02-05 21:41:13 +01:00
|
|
|
{
|
|
|
|
const Engine *e = ::Engine::GetIfValid(this->engine);
|
|
|
|
return e != NULL && e->IsEnabled();
|
|
|
|
}
|
|
|
|
|
2011-11-30 00:15:35 +01:00
|
|
|
char *ScriptEventEnginePreview::GetName()
|
2009-01-12 18:11:45 +01:00
|
|
|
{
|
2011-02-05 21:41:13 +01:00
|
|
|
if (!this->IsEngineValid()) return NULL;
|
2009-01-12 18:11:45 +01:00
|
|
|
|
2009-09-01 14:33:17 +02:00
|
|
|
::SetDParam(0, this->engine);
|
2012-01-08 22:48:05 +01:00
|
|
|
return GetString(STR_ENGINE_NAME);
|
2009-01-12 18:11:45 +01:00
|
|
|
}
|
|
|
|
|
2011-11-30 00:15:35 +01:00
|
|
|
CargoID ScriptEventEnginePreview::GetCargoType()
|
2009-01-12 18:11:45 +01:00
|
|
|
{
|
2011-02-05 21:41:13 +01:00
|
|
|
if (!this->IsEngineValid()) return CT_INVALID;
|
2009-10-28 21:15:46 +01:00
|
|
|
CargoArray cap = ::GetCapacityOfArticulatedParts(this->engine);
|
|
|
|
|
|
|
|
CargoID most_cargo = CT_INVALID;
|
|
|
|
uint amount = 0;
|
|
|
|
for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
|
|
|
|
if (cap[cid] > amount) {
|
|
|
|
amount = cap[cid];
|
|
|
|
most_cargo = cid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return most_cargo;
|
2009-01-12 18:11:45 +01:00
|
|
|
}
|
|
|
|
|
2011-11-30 00:15:35 +01:00
|
|
|
int32 ScriptEventEnginePreview::GetCapacity()
|
2009-01-12 18:11:45 +01:00
|
|
|
{
|
2011-02-05 21:41:13 +01:00
|
|
|
if (!this->IsEngineValid()) return -1;
|
2009-09-01 14:33:17 +02:00
|
|
|
const Engine *e = ::Engine::Get(this->engine);
|
2009-03-14 00:49:12 +01:00
|
|
|
switch (e->type) {
|
2009-01-12 18:11:45 +01:00
|
|
|
case VEH_ROAD:
|
|
|
|
case VEH_TRAIN: {
|
2009-10-06 21:52:38 +02:00
|
|
|
CargoArray capacities = GetCapacityOfArticulatedParts(this->engine);
|
2009-01-12 18:11:45 +01:00
|
|
|
for (CargoID c = 0; c < NUM_CARGO; c++) {
|
|
|
|
if (capacities[c] == 0) continue;
|
|
|
|
return capacities[c];
|
|
|
|
}
|
|
|
|
return -1;
|
2010-08-01 20:53:30 +02:00
|
|
|
}
|
2009-01-12 18:11:45 +01:00
|
|
|
|
2009-03-14 00:49:12 +01:00
|
|
|
case VEH_SHIP:
|
|
|
|
case VEH_AIRCRAFT:
|
2009-03-18 20:32:13 +01:00
|
|
|
return e->GetDisplayDefaultCapacity();
|
2009-01-12 18:11:45 +01:00
|
|
|
|
|
|
|
default: NOT_REACHED();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-30 00:15:35 +01:00
|
|
|
int32 ScriptEventEnginePreview::GetMaxSpeed()
|
2009-01-12 18:11:45 +01:00
|
|
|
{
|
2011-02-05 21:41:13 +01:00
|
|
|
if (!this->IsEngineValid()) return -1;
|
2009-09-01 14:33:17 +02:00
|
|
|
const Engine *e = ::Engine::Get(this->engine);
|
2009-02-01 18:14:39 +01:00
|
|
|
int32 max_speed = e->GetDisplayMaxSpeed(); // km-ish/h
|
2009-02-01 17:10:06 +01:00
|
|
|
if (e->type == VEH_AIRCRAFT) max_speed /= _settings_game.vehicle.plane_speed;
|
|
|
|
return max_speed;
|
2009-01-12 18:11:45 +01:00
|
|
|
}
|
|
|
|
|
2011-11-30 00:15:35 +01:00
|
|
|
Money ScriptEventEnginePreview::GetPrice()
|
2009-01-12 18:11:45 +01:00
|
|
|
{
|
2011-02-05 21:41:13 +01:00
|
|
|
if (!this->IsEngineValid()) return -1;
|
2009-09-01 14:33:17 +02:00
|
|
|
return ::Engine::Get(this->engine)->GetCost();
|
2009-01-12 18:11:45 +01:00
|
|
|
}
|
|
|
|
|
2011-11-30 00:15:35 +01:00
|
|
|
Money ScriptEventEnginePreview::GetRunningCost()
|
2009-01-12 18:11:45 +01:00
|
|
|
{
|
2011-02-05 21:41:13 +01:00
|
|
|
if (!this->IsEngineValid()) return -1;
|
2009-09-01 14:33:17 +02:00
|
|
|
return ::Engine::Get(this->engine)->GetRunningCost();
|
2009-01-12 18:11:45 +01:00
|
|
|
}
|
|
|
|
|
2011-11-30 00:15:35 +01:00
|
|
|
int32 ScriptEventEnginePreview::GetVehicleType()
|
2009-01-12 18:11:45 +01:00
|
|
|
{
|
2011-11-30 00:15:35 +01:00
|
|
|
if (!this->IsEngineValid()) return ScriptVehicle::VT_INVALID;
|
2009-09-01 14:33:17 +02:00
|
|
|
switch (::Engine::Get(this->engine)->type) {
|
2011-11-30 00:15:35 +01:00
|
|
|
case VEH_ROAD: return ScriptVehicle::VT_ROAD;
|
|
|
|
case VEH_TRAIN: return ScriptVehicle::VT_RAIL;
|
|
|
|
case VEH_SHIP: return ScriptVehicle::VT_WATER;
|
|
|
|
case VEH_AIRCRAFT: return ScriptVehicle::VT_AIR;
|
2009-01-12 18:11:45 +01:00
|
|
|
default: NOT_REACHED();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-30 00:15:35 +01:00
|
|
|
bool ScriptEventEnginePreview::AcceptPreview()
|
2009-01-12 18:11:45 +01:00
|
|
|
{
|
2011-02-05 21:41:13 +01:00
|
|
|
if (!this->IsEngineValid()) return false;
|
2011-11-30 00:15:35 +01:00
|
|
|
return ScriptObject::DoCommand(0, this->engine, 0, CMD_WANT_ENGINE_PREVIEW);
|
2009-01-12 18:11:45 +01:00
|
|
|
}
|
2009-09-01 14:57:04 +02:00
|
|
|
|
2011-11-30 00:15:35 +01:00
|
|
|
bool ScriptEventCompanyAskMerger::AcceptMerger()
|
2009-09-01 14:57:04 +02:00
|
|
|
{
|
2011-11-30 00:15:35 +01:00
|
|
|
return ScriptObject::DoCommand(0, this->owner, 0, CMD_BUY_COMPANY);
|
2009-09-01 14:57:04 +02:00
|
|
|
}
|
2011-12-19 22:00:32 +01:00
|
|
|
|
2014-04-25 17:40:32 +02:00
|
|
|
ScriptEventAdminPort::ScriptEventAdminPort(const char *json) :
|
|
|
|
ScriptEvent(ET_ADMIN_PORT),
|
|
|
|
json(stredup(json))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ScriptEventAdminPort::~ScriptEventAdminPort()
|
|
|
|
{
|
|
|
|
free(this->json);
|
|
|
|
}
|
|
|
|
|
2011-12-19 22:00:32 +01:00
|
|
|
#define SKIP_EMPTY(p) while (*(p) == ' ' || *(p) == '\n' || *(p) == '\r') (p)++;
|
|
|
|
#define RETURN_ERROR(stack) { ScriptLog::Error("Received invalid JSON data from AdminPort."); if (stack != 0) sq_pop(vm, stack); return NULL; }
|
|
|
|
|
|
|
|
SQInteger ScriptEventAdminPort::GetObject(HSQUIRRELVM vm)
|
|
|
|
{
|
|
|
|
char *p = this->json;
|
|
|
|
|
|
|
|
if (this->ReadTable(vm, p) == NULL) {
|
|
|
|
sq_pushnull(vm);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *ScriptEventAdminPort::ReadString(HSQUIRRELVM vm, char *p)
|
|
|
|
{
|
|
|
|
char *value = p;
|
|
|
|
|
|
|
|
bool escape = false;
|
|
|
|
for (;;) {
|
|
|
|
if (*p == '\\') {
|
|
|
|
escape = true;
|
|
|
|
p++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (*p == '"' && escape) {
|
|
|
|
escape = false;
|
|
|
|
p++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
escape = false;
|
|
|
|
|
|
|
|
if (*p == '"') break;
|
|
|
|
if (*p == '\0') RETURN_ERROR(0);
|
|
|
|
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*p = '\0';
|
2014-09-06 19:30:33 +02:00
|
|
|
sq_pushstring(vm, value, -1);
|
2011-12-19 22:00:32 +01:00
|
|
|
*p++ = '"';
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *ScriptEventAdminPort::ReadTable(HSQUIRRELVM vm, char *p)
|
|
|
|
{
|
|
|
|
sq_newtable(vm);
|
|
|
|
|
|
|
|
SKIP_EMPTY(p);
|
|
|
|
if (*p++ != '{') RETURN_ERROR(1);
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
SKIP_EMPTY(p);
|
|
|
|
if (*p++ != '"') RETURN_ERROR(1);
|
|
|
|
|
|
|
|
p = ReadString(vm, p);
|
|
|
|
if (p == NULL) {
|
|
|
|
sq_pop(vm, 1);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
SKIP_EMPTY(p);
|
|
|
|
if (*p++ != ':') RETURN_ERROR(2);
|
|
|
|
|
|
|
|
p = this->ReadValue(vm, p);
|
|
|
|
if (p == NULL) {
|
|
|
|
sq_pop(vm, 2);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
sq_rawset(vm, -3);
|
|
|
|
/* The key (-2) and value (-1) are popped from the stack by squirrel. */
|
|
|
|
|
|
|
|
SKIP_EMPTY(p);
|
|
|
|
if (*p == ',') {
|
|
|
|
p++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
SKIP_EMPTY(p);
|
|
|
|
if (*p++ != '}') RETURN_ERROR(1);
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *ScriptEventAdminPort::ReadValue(HSQUIRRELVM vm, char *p)
|
|
|
|
{
|
|
|
|
SKIP_EMPTY(p);
|
|
|
|
|
|
|
|
if (strncmp(p, "false", 5) == 0) {
|
|
|
|
sq_pushinteger(vm, 0);
|
|
|
|
return p + 5;
|
|
|
|
}
|
|
|
|
if (strncmp(p, "true", 4) == 0) {
|
|
|
|
sq_pushinteger(vm, 1);
|
|
|
|
return p + 4;
|
|
|
|
}
|
|
|
|
if (strncmp(p, "null", 4) == 0) {
|
|
|
|
sq_pushnull(vm);
|
|
|
|
return p + 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (*p) {
|
|
|
|
case '"': {
|
|
|
|
/* String */
|
|
|
|
p = ReadString(vm, ++p);
|
|
|
|
if (p == NULL) return NULL;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case '{': {
|
|
|
|
/* Table */
|
|
|
|
p = this->ReadTable(vm, p);
|
|
|
|
if (p == NULL) return NULL;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case '[': {
|
|
|
|
/* Array */
|
|
|
|
sq_newarray(vm, 0);
|
|
|
|
|
2013-10-03 18:47:24 +02:00
|
|
|
/* Empty array? */
|
|
|
|
char *p2 = p+1;
|
|
|
|
SKIP_EMPTY(p2);
|
|
|
|
if (*p2 == ']') {
|
|
|
|
p = p2+1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-12-19 22:00:32 +01:00
|
|
|
while (*p++ != ']') {
|
|
|
|
p = this->ReadValue(vm, p);
|
|
|
|
if (p == NULL) {
|
|
|
|
sq_pop(vm, 1);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
sq_arrayappend(vm, -2);
|
|
|
|
|
|
|
|
SKIP_EMPTY(p);
|
|
|
|
if (*p == ',') continue;
|
|
|
|
if (*p == ']') break;
|
|
|
|
RETURN_ERROR(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
p++;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case '1': case '2': case '3': case '4': case '5':
|
|
|
|
case '6': case '7': case '8': case '9': case '0':
|
|
|
|
case '-': {
|
|
|
|
/* Integer */
|
|
|
|
|
|
|
|
const char *value = p++;
|
|
|
|
for (;;) {
|
|
|
|
switch (*p++) {
|
|
|
|
case '1': case '2': case '3': case '4': case '5':
|
|
|
|
case '6': case '7': case '8': case '9': case '0':
|
|
|
|
continue;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
p--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
int res = atoi(value);
|
|
|
|
sq_pushinteger(vm, (SQInteger)res);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
RETURN_ERROR(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef SKIP_EMPTY
|
|
|
|
#undef RETURN_ERROR
|