diff --git a/src/command.cpp b/src/command.cpp index 2522d4af35..5710f0bb64 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -142,6 +142,7 @@ CommandProc CmdClearArea; CommandProc CmdGiveMoney; CommandProc CmdMoneyCheat; +CommandProc CmdChangeBankBalance; CommandProc CmdBuildCanal; CommandProc CmdBuildLock; @@ -295,6 +296,7 @@ static const Command _command_proc_table[] = { DEF_CMD(CmdClearArea, CMD_NO_TEST, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_CLEAR_AREA; destroying multi-tile houses makes town rating differ between test and execution DEF_CMD(CmdMoneyCheat, CMD_OFFLINE, CMDT_CHEAT ), // CMD_MONEY_CHEAT + DEF_CMD(CmdChangeBankBalance, CMD_DEITY, CMDT_MONEY_MANAGEMENT ), // CMD_CHANGE_BANK_BALANCE DEF_CMD(CmdBuildCanal, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_BUILD_CANAL DEF_CMD(CmdCreateSubsidy, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_CREATE_SUBSIDY DEF_CMD(CmdCompanyCtrl, CMD_SPECTATOR | CMD_CLIENT_ID, CMDT_SERVER_SETTING ), // CMD_COMPANY_CTRL diff --git a/src/command_type.h b/src/command_type.h index f3236f261c..6e3ccd3ae8 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -259,6 +259,7 @@ enum Commands { CMD_CLEAR_AREA, ///< clear an area CMD_MONEY_CHEAT, ///< do the money cheat + CMD_CHANGE_BANK_BALANCE, ///< change bank balance to charge costs or give money from a GS CMD_BUILD_CANAL, ///< build a canal CMD_CREATE_SUBSIDY, ///< create a new subsidy diff --git a/src/economy_type.h b/src/economy_type.h index a15f4b5e3a..7e7a572413 100644 --- a/src/economy_type.h +++ b/src/economy_type.h @@ -165,6 +165,10 @@ enum ExpensesType { INVALID_EXPENSES = 0xFF, ///< Invalid expense type. }; +/** Define basic enum properties for ExpensesType */ +template <> struct EnumPropsT : MakeEnumPropsT {}; +typedef TinyEnumT ExpensesTypeByte; ///< typedefing-enumification of ExpensesType + /** * Categories of a price bases. */ diff --git a/src/misc_cmd.cpp b/src/misc_cmd.cpp index df76e15351..c35ccc8f82 100644 --- a/src/misc_cmd.cpp +++ b/src/misc_cmd.cpp @@ -12,6 +12,7 @@ #include "stdafx.h" #include "command_func.h" #include "economy_func.h" +#include "cmd_helper.h" #include "window_func.h" #include "textbuf_gui.h" #include "network/network.h" @@ -204,6 +205,38 @@ CommandCost CmdMoneyCheat(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 return CommandCost(EXPENSES_OTHER, -(int32)p1); } +/** + * Change the bank bank balance of a company by inserting or removing money without affecting the loan. + * @param tile unused + * @param flags operation to perform + * @param p1 the amount of money to receive (if positive), or spend (if negative) + * @param p2 (bit 0-7) - the company ID. + * (bit 8-15) - the expenses type which should register the cost/income @see ExpensesType. + * @param text unused + * @return zero cost or an error + */ +CommandCost CmdChangeBankBalance(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + int32 delta = (int32)p1; + CompanyID company = (CompanyID) GB(p2, 0, 8); + ExpensesType expenses_type = Extract(p2); + + if (!Company::IsValidID(company)) return CMD_ERROR; + if (expenses_type >= EXPENSES_END) return CMD_ERROR; + if (_current_company != OWNER_DEITY) return CMD_ERROR; + + if (flags & DC_EXEC) { + /* Change company bank balance of company. */ + Backup cur_company(_current_company, company, FILE_LINE); + SubtractMoneyFromCompany(CommandCost(expenses_type, -delta)); + cur_company.Restore(); + } + + /* This command doesn't cost anyting for deity. */ + CommandCost zero_cost(expenses_type, 0); + return zero_cost; +} + /** * Transfer funds (money) from one company to another. * To prevent abuse in multiplayer games you can only send money to other diff --git a/src/script/api/game/game_company.hpp.sq b/src/script/api/game/game_company.hpp.sq index 98c6d44764..f53d55baa5 100644 --- a/src/script/api/game/game_company.hpp.sq +++ b/src/script/api/game/game_company.hpp.sq @@ -21,15 +21,29 @@ void SQGSCompany_Register(Squirrel *engine) SQGSCompany.PreRegister(engine); SQGSCompany.AddConstructor(engine, "x"); - SQGSCompany.DefSQConst(engine, ScriptCompany::CURRENT_QUARTER, "CURRENT_QUARTER"); - SQGSCompany.DefSQConst(engine, ScriptCompany::EARLIEST_QUARTER, "EARLIEST_QUARTER"); - SQGSCompany.DefSQConst(engine, ScriptCompany::COMPANY_FIRST, "COMPANY_FIRST"); - SQGSCompany.DefSQConst(engine, ScriptCompany::COMPANY_LAST, "COMPANY_LAST"); - SQGSCompany.DefSQConst(engine, ScriptCompany::COMPANY_INVALID, "COMPANY_INVALID"); - SQGSCompany.DefSQConst(engine, ScriptCompany::COMPANY_SELF, "COMPANY_SELF"); - SQGSCompany.DefSQConst(engine, ScriptCompany::GENDER_MALE, "GENDER_MALE"); - SQGSCompany.DefSQConst(engine, ScriptCompany::GENDER_FEMALE, "GENDER_FEMALE"); - SQGSCompany.DefSQConst(engine, ScriptCompany::GENDER_INVALID, "GENDER_INVALID"); + SQGSCompany.DefSQConst(engine, ScriptCompany::CURRENT_QUARTER, "CURRENT_QUARTER"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EARLIEST_QUARTER, "EARLIEST_QUARTER"); + SQGSCompany.DefSQConst(engine, ScriptCompany::COMPANY_FIRST, "COMPANY_FIRST"); + SQGSCompany.DefSQConst(engine, ScriptCompany::COMPANY_LAST, "COMPANY_LAST"); + SQGSCompany.DefSQConst(engine, ScriptCompany::COMPANY_INVALID, "COMPANY_INVALID"); + SQGSCompany.DefSQConst(engine, ScriptCompany::COMPANY_SELF, "COMPANY_SELF"); + SQGSCompany.DefSQConst(engine, ScriptCompany::GENDER_MALE, "GENDER_MALE"); + SQGSCompany.DefSQConst(engine, ScriptCompany::GENDER_FEMALE, "GENDER_FEMALE"); + SQGSCompany.DefSQConst(engine, ScriptCompany::GENDER_INVALID, "GENDER_INVALID"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EXPENSES_CONSTRUCTION, "EXPENSES_CONSTRUCTION"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EXPENSES_NEW_VEHICLES, "EXPENSES_NEW_VEHICLES"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EXPENSES_TRAIN_RUN, "EXPENSES_TRAIN_RUN"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EXPENSES_ROADVEH_RUN, "EXPENSES_ROADVEH_RUN"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EXPENSES_AIRCRAFT_RUN, "EXPENSES_AIRCRAFT_RUN"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EXPENSES_SHIP_RUN, "EXPENSES_SHIP_RUN"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EXPENSES_PROPERTY, "EXPENSES_PROPERTY"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EXPENSES_TRAIN_INC, "EXPENSES_TRAIN_INC"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EXPENSES_ROADVEH_INC, "EXPENSES_ROADVEH_INC"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EXPENSES_AIRCRAFT_INC, "EXPENSES_AIRCRAFT_INC"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EXPENSES_SHIP_INC, "EXPENSES_SHIP_INC"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EXPENSES_LOAN_INT, "EXPENSES_LOAN_INT"); + SQGSCompany.DefSQConst(engine, ScriptCompany::EXPENSES_OTHER, "EXPENSES_OTHER"); + SQGSCompany.DefSQConst(engine, ScriptCompany::INVALID_EXPENSES, "INVALID_EXPENSES"); SQGSCompany.DefSQStaticMethod(engine, &ScriptCompany::ResolveCompanyID, "ResolveCompanyID", 2, ".i"); SQGSCompany.DefSQStaticMethod(engine, &ScriptCompany::SetName, "SetName", 2, ".."); @@ -43,6 +57,7 @@ void SQGSCompany_Register(Squirrel *engine) SQGSCompany.DefSQStaticMethod(engine, &ScriptCompany::GetMaxLoanAmount, "GetMaxLoanAmount", 1, "."); SQGSCompany.DefSQStaticMethod(engine, &ScriptCompany::GetLoanInterval, "GetLoanInterval", 1, "."); SQGSCompany.DefSQStaticMethod(engine, &ScriptCompany::GetBankBalance, "GetBankBalance", 2, ".i"); + SQGSCompany.DefSQStaticMethod(engine, &ScriptCompany::ChangeBankBalance, "ChangeBankBalance", 4, ".iii"); SQGSCompany.DefSQStaticMethod(engine, &ScriptCompany::GetQuarterlyIncome, "GetQuarterlyIncome", 3, ".ii"); SQGSCompany.DefSQStaticMethod(engine, &ScriptCompany::GetQuarterlyExpenses, "GetQuarterlyExpenses", 3, ".ii"); SQGSCompany.DefSQStaticMethod(engine, &ScriptCompany::GetQuarterlyCargoDelivered, "GetQuarterlyCargoDelivered", 3, ".ii"); diff --git a/src/script/api/game_changelog.hpp b/src/script/api/game_changelog.hpp index ebab776a4a..59893a19a7 100644 --- a/src/script/api/game_changelog.hpp +++ b/src/script/api/game_changelog.hpp @@ -20,6 +20,7 @@ * 1.4.0 is not yet released. The following changes are not set in stone yet. * * API additions: + * \li GSCompany::ChangeBankBalance * \li GSGoal::IsCompleted * \li GSGoal::SetCompleted * \li GSGoal::SetProgress diff --git a/src/script/api/script_company.cpp b/src/script/api/script_company.cpp index 2f06fd69de..01c2ce6ec1 100644 --- a/src/script/api/script_company.cpp +++ b/src/script/api/script_company.cpp @@ -12,6 +12,7 @@ #include "../../stdafx.h" #include "script_company.hpp" #include "script_error.hpp" +#include "script_companymode.hpp" #include "../../company_func.h" #include "../../company_base.h" #include "../../company_manager_face.h" @@ -223,6 +224,17 @@ return GetLoanAmount() == loan; } +/* static */ bool ScriptCompany::ChangeBankBalance(CompanyID company, int32 delta, ExpensesType expenses_type) +{ + EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY); + EnforcePrecondition(false, expenses_type < ::EXPENSES_END); + + company = ResolveCompanyID(company); + EnforcePrecondition(false, ResolveCompanyID(company) != COMPANY_INVALID); + + return ScriptObject::DoCommand(0, (uint32)(delta), company | expenses_type << 8 , CMD_CHANGE_BANK_BALANCE); +} + /* static */ bool ScriptCompany::BuildCompanyHQ(TileIndex tile) { EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY); diff --git a/src/script/api/script_company.hpp b/src/script/api/script_company.hpp index e6c3dcb31c..3499619619 100644 --- a/src/script/api/script_company.hpp +++ b/src/script/api/script_company.hpp @@ -13,6 +13,7 @@ #define SCRIPT_COMPANY_HPP #include "script_text.hpp" +#include "../../economy_type.h" /** * Class that handles all company related functions. @@ -44,6 +45,27 @@ public: GENDER_INVALID = -1, ///< An invalid gender. }; + /** + * Types of expenses. + * @api -ai + */ + enum ExpensesType { + EXPENSES_CONSTRUCTION = ::EXPENSES_CONSTRUCTION, ///< Construction costs. + EXPENSES_NEW_VEHICLES = ::EXPENSES_NEW_VEHICLES, ///< New vehicles. + EXPENSES_TRAIN_RUN = ::EXPENSES_TRAIN_RUN, ///< Running costs trains. + EXPENSES_ROADVEH_RUN = ::EXPENSES_ROADVEH_RUN, ///< Running costs road vehicles. + EXPENSES_AIRCRAFT_RUN = ::EXPENSES_AIRCRAFT_RUN, ///< Running costs aircrafts. + EXPENSES_SHIP_RUN = ::EXPENSES_SHIP_RUN, ///< Running costs ships. + EXPENSES_PROPERTY = ::EXPENSES_PROPERTY, ///< Property costs. + EXPENSES_TRAIN_INC = ::EXPENSES_TRAIN_INC, ///< Income from trains. + EXPENSES_ROADVEH_INC = ::EXPENSES_ROADVEH_INC, ///< Income from road vehicles. + EXPENSES_AIRCRAFT_INC = ::EXPENSES_AIRCRAFT_INC, ///< Income from aircrafts. + EXPENSES_SHIP_INC = ::EXPENSES_SHIP_INC, ///< Income from ships. + EXPENSES_LOAN_INT = ::EXPENSES_LOAN_INT, ///< Interest payments over the loan. + EXPENSES_OTHER = ::EXPENSES_OTHER, ///< Other expenses. + INVALID_EXPENSES = ::INVALID_EXPENSES, ///< Invalid expense type. + }; + /** * Resolved the given company index to the correct index for the company. If * the company index was COMPANY_SELF it will be resolved to the index of @@ -164,6 +186,19 @@ public: */ static Money GetBankBalance(CompanyID company); + /** + * Changes the bank balance by a delta value. This method does not affect the loan but instead + * allows a GS to give or take money from a company. + * @param company The company to change the bank balance of. + * @param delta Amount of money to give or take from the bank balance. A positive value adds money to the bank balance. + * @param expenses_type The account in the finances window that will register the cost. + * @game @pre No ScriptCompanyMode active in scope. + * @pre ResolveCompanyID(company) != COMPANY_INVALID. + * @note You need to create your own news message to inform about costs/gifts that you create using this command. + * @api -ai + */ + static bool ChangeBankBalance(CompanyID company, int32 delta, ExpensesType expenses_type); + /** * Get the income of the company in the given quarter. * Note that this function only considers recurring income from vehicles; diff --git a/src/script/api/template/template_company.hpp.sq b/src/script/api/template/template_company.hpp.sq index 5668e893e7..7dc63f24bc 100644 --- a/src/script/api/template/template_company.hpp.sq +++ b/src/script/api/template/template_company.hpp.sq @@ -19,6 +19,8 @@ namespace SQConvert { template <> inline int Return(HSQUIRRELVM vm, ScriptCompany::CompanyID res) { sq_pushinteger(vm, (int32)res); return 1; } template <> inline ScriptCompany::Gender GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptCompany::Gender)tmp; } template <> inline int Return(HSQUIRRELVM vm, ScriptCompany::Gender res) { sq_pushinteger(vm, (int32)res); return 1; } + template <> inline ScriptCompany::ExpensesType GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptCompany::ExpensesType)tmp; } + template <> inline int Return(HSQUIRRELVM vm, ScriptCompany::ExpensesType res) { sq_pushinteger(vm, (int32)res); return 1; } /* Allow ScriptCompany to be used as Squirrel parameter */ template <> inline ScriptCompany *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptCompany *)instance; }