mirror of https://github.com/OpenTTD/OpenTTD
(svn r2300) - CodeChange: check the last number of commands, now only the refit ones remain, and some server-only commands.
- CodeChange: remove cmd-misuses CmdStartScenario() and CmdDestroyCompanyHQ() - Fix (invisible): when parameter checking CmdRestoreOrderIndex() the vehicle did not have its orders yet, so it would fail. So move doing this until AFTER the orders have been added back in RestoreVehicleOrders()release/0.4.5
parent
56e7e4cf25
commit
033995ec6e
24
clear_cmd.c
24
clear_cmd.c
|
@ -322,18 +322,21 @@ int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* p1 - start
|
||||
/** Levels a selected (rectangle) area of land
|
||||
* @param x,y end tile of area-drag
|
||||
* @param p1 start tile of area drag
|
||||
* @param p2 unused
|
||||
*/
|
||||
|
||||
int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int size_x, size_y;
|
||||
int sx, sy;
|
||||
uint h, curh;
|
||||
uint tile;
|
||||
TileIndex tile;
|
||||
int32 ret, cost, money;
|
||||
|
||||
if (p1 > MapSize()) return CMD_ERROR;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
// remember level height
|
||||
|
@ -354,11 +357,11 @@ int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
|
|||
money = GetAvailableMoneyForCommand();
|
||||
cost = 0;
|
||||
|
||||
BEGIN_TILE_LOOP(tile2, size_x, size_y, tile)
|
||||
BEGIN_TILE_LOOP(tile2, size_x, size_y, tile) {
|
||||
curh = TileHeight(tile2);
|
||||
while (curh != h) {
|
||||
ret = DoCommandByTile(tile2, 8, (curh > h)?0:1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
|
||||
if (ret == CMD_ERROR) break;
|
||||
ret = DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
|
||||
if (CmdFailed(ret)) break;
|
||||
cost += ret;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
|
@ -366,15 +369,14 @@ int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
|
|||
_additional_cash_required = ret;
|
||||
return cost - ret;
|
||||
}
|
||||
DoCommandByTile(tile2, 8, (curh > h)?0:1, flags, CMD_TERRAFORM_LAND);
|
||||
DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
|
||||
}
|
||||
|
||||
curh += (curh > h) ? -1 : 1;
|
||||
}
|
||||
END_TILE_LOOP(tile2, size_x, size_y, tile)
|
||||
} END_TILE_LOOP(tile2, size_x, size_y, tile)
|
||||
|
||||
if (cost == 0) return CMD_ERROR;
|
||||
return cost;
|
||||
return (cost == 0) ? CMD_ERROR : cost;
|
||||
}
|
||||
|
||||
/** Purchase a land area. Actually you only purchase one tile, so
|
||||
|
|
32
command.c
32
command.c
|
@ -77,7 +77,6 @@ DEF_COMMAND(CmdRestoreOrderIndex);
|
|||
DEF_COMMAND(CmdBuildIndustry);
|
||||
|
||||
DEF_COMMAND(CmdBuildCompanyHQ);
|
||||
DEF_COMMAND(CmdDestroyCompanyHQ);
|
||||
DEF_COMMAND(CmdSetPlayerFace);
|
||||
DEF_COMMAND(CmdSetPlayerColor);
|
||||
|
||||
|
@ -149,8 +148,6 @@ DEF_COMMAND(CmdLevelLand);
|
|||
|
||||
DEF_COMMAND(CmdRefitRailVehicle);
|
||||
|
||||
DEF_COMMAND(CmdStartScenario);
|
||||
|
||||
DEF_COMMAND(CmdBuildSignalTrack);
|
||||
DEF_COMMAND(CmdRemoveSignalTrack);
|
||||
|
||||
|
@ -232,7 +229,7 @@ static CommandProc * const _command_proc_table[] = {
|
|||
CmdBuildAircraft, /* 61 */
|
||||
CmdSendAircraftToHangar, /* 62 */
|
||||
CmdChangeAircraftServiceInt, /* 63 */
|
||||
CmdRefitAircraft, /* 64 <-- Hackykid */
|
||||
CmdRefitAircraft, /* 64 <-- REFIT: Hackykid */
|
||||
|
||||
CmdPlaceSign, /* 65 */
|
||||
CmdRenameSign, /* 66 */
|
||||
|
@ -250,7 +247,7 @@ static CommandProc * const _command_proc_table[] = {
|
|||
CmdSellShareInCompany, /* 75 */
|
||||
CmdBuyCompany, /* 76 */
|
||||
|
||||
CmdBuildTown, /* 77 <-- offline / scenario only */
|
||||
CmdBuildTown, /* 77 <-- offline */
|
||||
NULL, /* 78 */
|
||||
NULL, /* 79 */
|
||||
CmdRenameTown, /* 80 <-- TODO: check/enforce by server */
|
||||
|
@ -266,7 +263,7 @@ static CommandProc * const _command_proc_table[] = {
|
|||
CmdBuildShip, /* 88 */
|
||||
CmdSendShipToDepot, /* 89 */
|
||||
CmdChangeShipServiceInt, /* 90 */
|
||||
CmdRefitShip, /* 91 <-- Hackykid */
|
||||
CmdRefitShip, /* 91 <-- REFIT: Hackykid */
|
||||
|
||||
NULL, /* 92 */
|
||||
NULL, /* 93 */
|
||||
|
@ -274,30 +271,29 @@ static CommandProc * const _command_proc_table[] = {
|
|||
NULL, /* 95 */
|
||||
NULL, /* 96 */
|
||||
NULL, /* 97 */
|
||||
|
||||
NULL, /* 98 */
|
||||
|
||||
CmdCloneOrder, /* 99 */
|
||||
|
||||
CmdClearArea, /* 100 */
|
||||
NULL, /* 101 */
|
||||
/***************************************************/
|
||||
CmdMoneyCheat, /* 102 <-- offline only */
|
||||
|
||||
CmdMoneyCheat, /* 102 <-- offline (debug) */
|
||||
CmdBuildCanal, /* 103 */
|
||||
CmdPlayerCtrl, /* 104 <-- TODO: check/enforce by server */
|
||||
CmdPlayerCtrl, /* 104 */
|
||||
|
||||
CmdLevelLand, /* 105 <-- Hackykid */
|
||||
CmdLevelLand, /* 105 */
|
||||
|
||||
CmdRefitRailVehicle, /* 106 <-- Hackykid */
|
||||
CmdRefitRailVehicle, /* 106 <-- REFIT: Hackykid */
|
||||
CmdRestoreOrderIndex, /* 107 */
|
||||
CmdBuildLock, /* 108 <-- Hackykid */
|
||||
CmdStartScenario, /* 109 <-- UNNEEDED */
|
||||
CmdBuildSignalTrack, /* 110 <-- Hackykid */
|
||||
CmdRemoveSignalTrack, /* 111 <-- Hackykid */
|
||||
CmdDestroyCompanyHQ, /* 112 */
|
||||
CmdBuildLock, /* 108 */
|
||||
NULL, /* 109 */
|
||||
CmdBuildSignalTrack, /* 110 */
|
||||
CmdRemoveSignalTrack, /* 111 */
|
||||
NULL, /* 112 */
|
||||
CmdGiveMoney, /* 113 */
|
||||
CmdChangePatchSetting, /* 114 <-- TODO: check/enforce by server */
|
||||
CmdReplaceVehicle, /* 115 <-- Hackykid */
|
||||
CmdReplaceVehicle, /* 115 */
|
||||
};
|
||||
|
||||
/* This function range-checks a cmd, and checks if the cmd is not NULL */
|
||||
|
|
11
command.h
11
command.h
|
@ -104,8 +104,6 @@ enum {
|
|||
CMD_DO_TOWN_ACTION = 81,
|
||||
|
||||
CMD_SET_ROAD_DRIVE_SIDE = 82,
|
||||
CMD_SET_TOWN_NAME_TYPE = 83,
|
||||
|
||||
|
||||
CMD_CHANGE_DIFFICULTY_LEVEL = 85,
|
||||
|
||||
|
@ -116,13 +114,6 @@ enum {
|
|||
CMD_CHANGE_SHIP_SERVICE_INT = 90,
|
||||
CMD_REFIT_SHIP = 91,
|
||||
|
||||
CMD_START_NEW_GAME = 92,
|
||||
CMD_CREATE_SCENARIO = 94,
|
||||
|
||||
CMD_SET_NEW_LANDSCAPE_TYPE = 97,
|
||||
|
||||
CMD_GEN_RANDOM_NEW_GAME = 98,
|
||||
|
||||
CMD_CLONE_ORDER = 99,
|
||||
CMD_CLEAR_AREA = 100,
|
||||
|
||||
|
@ -136,11 +127,9 @@ enum {
|
|||
CMD_RESTORE_ORDER_INDEX = 107,
|
||||
CMD_BUILD_LOCK = 108,
|
||||
|
||||
CMD_START_SCENARIO = 109,
|
||||
CMD_BUILD_SIGNAL_TRACK = 110,
|
||||
CMD_REMOVE_SIGNAL_TRACK = 111,
|
||||
|
||||
CMD_DESTROY_COMPANY_HQ = 112,
|
||||
CMD_GIVE_MONEY = 113,
|
||||
CMD_CHANGE_PATCH_SETTING = 114,
|
||||
|
||||
|
|
|
@ -229,6 +229,7 @@ int SaveOrLoad(const char *filename, int mode);
|
|||
|
||||
void AfterLoadTown(void);
|
||||
void GenRandomNewGame(uint32 rnd1, uint32 rnd2);
|
||||
void StartScenarioEditor(uint32 rnd1, uint32 rnd2);
|
||||
void AskExitGame(void);
|
||||
void AskExitToGameMenu(void);
|
||||
|
||||
|
|
14
intro_gui.c
14
intro_gui.c
|
@ -137,22 +137,14 @@ void GenRandomNewGame(uint32 rnd1, uint32 rnd2)
|
|||
SwitchMode(SM_NEWGAME);
|
||||
}
|
||||
|
||||
int32 CmdStartScenario(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
void StartScenarioEditor(uint32 rnd1, uint32 rnd2)
|
||||
{
|
||||
if (!(flags & DC_EXEC))
|
||||
return 0;
|
||||
|
||||
// this forces stuff into test mode.
|
||||
_docommand_recursive = 0;
|
||||
|
||||
_random_seeds[0][0] = p1;
|
||||
_random_seeds[0][1] = p2;
|
||||
_random_seeds[0][0] = rnd1;
|
||||
_random_seeds[0][1] = rnd2;
|
||||
|
||||
SwitchMode(SM_START_SCENARIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const Widget _ask_abandon_game_widgets[] = {
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 4, 0, 10, 0, 13, STR_00C5, STR_NULL},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 4, 11, 179, 0, 13, STR_00C7_QUIT, STR_NULL},
|
||||
|
|
27
misc_cmd.c
27
misc_cmd.c
|
@ -191,31 +191,42 @@ int32 CmdPause(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Change the financial flow of your company.
|
||||
* This is normally only enabled in offline mode, but if there is a debug
|
||||
* build, you can cheat (to test).
|
||||
* @param x,y unused
|
||||
* @param p1 the amount of money to receive (if negative), or spend (if positive)
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdMoneyCheat(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
#ifndef _DEBUG
|
||||
if (_networking) return CMD_ERROR;
|
||||
#endif
|
||||
SET_EXPENSES_TYPE(EXPENSES_OTHER);
|
||||
return (int32)p1;
|
||||
}
|
||||
|
||||
/** Transfer funds (money) from one player to another.
|
||||
* @param x,y unused
|
||||
* @param p1 the amount of money to transfer; max 16.000.000
|
||||
* @param p2 the player to transfer the money to
|
||||
*/
|
||||
int32 CmdGiveMoney(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
SET_EXPENSES_TYPE(EXPENSES_OTHER);
|
||||
|
||||
p1 = clamp(p1, 0, 0xFFFFFF); // Clamp between 16 million and 0
|
||||
|
||||
if (p1 == 0)
|
||||
return CMD_ERROR;
|
||||
if (!_networking || (int32)p1 <= 0 || p2 >= MAX_PLAYERS) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
// Add money to player
|
||||
byte old_cp = _current_player;
|
||||
/* Add money to player (cast to signed to prevent 'stealing' money) */
|
||||
PlayerID old_cp = _current_player;
|
||||
_current_player = p2;
|
||||
SubtractMoneyFromPlayer(-(int32)p1);
|
||||
_current_player = old_cp;
|
||||
}
|
||||
|
||||
// Subtract money from local-player
|
||||
/* Subtract money from local-player (cast to signed to prevent 'stealing' money) */
|
||||
return (int32)p1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1496,7 +1496,7 @@ static void SelectScenarioWndProc(Window *w, WindowEvent *e) {
|
|||
SetFiosType(file->type);
|
||||
strcpy(_file_to_saveload.name, name);
|
||||
DeleteWindow(w);
|
||||
DoCommandP(0, Random(), InteractiveRandom(), NULL, CMD_START_SCENARIO);
|
||||
StartScenarioEditor(Random(), InteractiveRandom());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -572,7 +572,7 @@ static void NetworkStartServerWindowWndProc(Window *w, WindowEvent *e)
|
|||
strcpy(_file_to_saveload.name, name);
|
||||
snprintf(_network_game_info.map_name, sizeof(_network_game_info.map_name), "Loaded scenario");
|
||||
DeleteWindow(w);
|
||||
DoCommandP(0, Random(), InteractiveRandom(), NULL, CMD_START_SCENARIO);
|
||||
StartScenarioEditor(Random(), InteractiveRandom());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
2
order.h
2
order.h
|
@ -141,7 +141,7 @@ static inline Order UnpackOrder(uint32 packed)
|
|||
}
|
||||
|
||||
/* Functions */
|
||||
void BackupVehicleOrders(Vehicle *v, BackuppedOrders *order);
|
||||
void BackupVehicleOrders(const Vehicle *v, BackuppedOrders *order);
|
||||
void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *order);
|
||||
void DeleteDestinationFromVehicleOrder(Order dest);
|
||||
void InvalidateVehicleOrder(const Vehicle *v);
|
||||
|
|
63
order_cmd.c
63
order_cmd.c
|
@ -697,6 +697,7 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
} break;
|
||||
|
||||
case CO_UNSHARE: return DecloneOrder(dst, flags);
|
||||
default: return CMD_ERROR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -708,10 +709,8 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
* without loosing the order-list
|
||||
*
|
||||
*/
|
||||
void BackupVehicleOrders(Vehicle *v, BackuppedOrders *bak)
|
||||
void BackupVehicleOrders(const Vehicle *v, BackuppedOrders *bak)
|
||||
{
|
||||
bool shared = IsOrderListShared(v);
|
||||
|
||||
/* Save general info */
|
||||
bak->orderindex = v->cur_order_index;
|
||||
bak->service_interval = v->service_interval;
|
||||
|
@ -724,19 +723,15 @@ void BackupVehicleOrders(Vehicle *v, BackuppedOrders *bak)
|
|||
}
|
||||
|
||||
/* If we have shared orders, store it on a special way */
|
||||
if (shared) {
|
||||
Vehicle *u;
|
||||
if (v->next_shared)
|
||||
u = v->next_shared;
|
||||
else
|
||||
u = v->prev_shared;
|
||||
if (IsOrderListShared(v)) {
|
||||
const Vehicle *u = (v->next_shared) ? v->next_shared : v->prev_shared;
|
||||
|
||||
bak->clone = u->index;
|
||||
} else {
|
||||
/* Else copy the orders */
|
||||
Order *order, *dest;
|
||||
|
||||
dest = bak->order;
|
||||
dest = bak->order;
|
||||
|
||||
/* We do not have shared orders */
|
||||
bak->clone = INVALID_VEHICLE;
|
||||
|
@ -759,7 +754,7 @@ void BackupVehicleOrders(Vehicle *v, BackuppedOrders *bak)
|
|||
*/
|
||||
void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak)
|
||||
{
|
||||
int i;
|
||||
uint i;
|
||||
|
||||
/* If we have a custom name, process that */
|
||||
if (bak->name[0] != 0) {
|
||||
|
@ -767,9 +762,6 @@ void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak)
|
|||
DoCommandP(0, v->index, 0, NULL, CMD_NAME_VEHICLE);
|
||||
}
|
||||
|
||||
/* Restore vehicle number and service interval */
|
||||
DoCommandP(0, v->index, bak->orderindex | (bak->service_interval << 16) , NULL, CMD_RESTORE_ORDER_INDEX);
|
||||
|
||||
/* If we had shared orders, recover that */
|
||||
if (bak->clone != INVALID_VEHICLE) {
|
||||
DoCommandP(0, v->index | (bak->clone << 16), 0, NULL, CMD_CLONE_ORDER);
|
||||
|
@ -780,31 +772,44 @@ void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak)
|
|||
order number is one more than the current amount of orders, and because
|
||||
in network the commands are queued before send, the second insert always
|
||||
fails in test mode. By bypassing the test-mode, that no longer is a problem. */
|
||||
for (i = 0; bak->order[i].type != OT_NOTHING; i++)
|
||||
for (i = 0; bak->order[i].type != OT_NOTHING; i++) {
|
||||
if (!DoCommandP(0, v->index + (i << 16), PackOrder(&bak->order[i]), NULL, CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Restore vehicle order-index and service interval */
|
||||
DoCommandP(0, v->index, bak->orderindex | (bak->service_interval << 16) , NULL, CMD_RESTORE_ORDER_INDEX);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Restore the current-order-index of a vehicle and sets service-interval
|
||||
*
|
||||
* @param vehicle_id The ID of the vehicle
|
||||
* @param data First 16 bits are the current-order-index
|
||||
* The last 16 bits are the service-interval
|
||||
*
|
||||
/** Restore the current order-index of a vehicle and sets service-interval.
|
||||
* @param x,y unused
|
||||
* @param p1 the ID of the vehicle
|
||||
* @param p2 various bistuffed elements
|
||||
* - p2 = (bit 0-15) - current order-index (p2 & 0xFFFF)
|
||||
* - p2 = (bit 16-31) - service interval (p2 >> 16)
|
||||
* @todo Unfortunately you cannot safely restore the unitnumber or the old vehicle
|
||||
* as far as I can see. We can store it in BackuppedOrders, and restore it, but
|
||||
* but we have no way of seeing it has been tampered with or not, as we have no
|
||||
* legit way of knowing what that ID was.@n
|
||||
* If we do want to backup/restore it, just add UnitID uid to BackuppedOrders, and
|
||||
* restore it as parameter 'y' (ugly hack I know) for example. "v->unitnumber = y;"
|
||||
*/
|
||||
int32 CmdRestoreOrderIndex(int x, int y, uint32 flags, uint32 vehicle_id, uint32 data)
|
||||
int32 CmdRestoreOrderIndex(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
Vehicle* v;
|
||||
Vehicle *v;
|
||||
OrderID cur_ord = p2 & 0xFFFF;
|
||||
uint16 serv_int = p2 >> 16;
|
||||
|
||||
if (!IsVehicleIndex(vehicle_id)) return CMD_ERROR;
|
||||
v = GetVehicle(vehicle_id);
|
||||
if (!IsVehicleIndex(p1)) return CMD_ERROR;
|
||||
|
||||
v = GetVehicle(p1);
|
||||
/* Check the vehicle type and ownership, and if the service interval and order are in range */
|
||||
if (v->type == 0 || !CheckOwnership(v->owner)) return CMD_ERROR;
|
||||
if (serv_int != GetServiceIntervalClamped(serv_int) || cur_ord >= v->num_orders) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
v->service_interval = data >> 16;
|
||||
v->cur_order_index = data & 0xFFFF;
|
||||
v->cur_order_index = cur_ord;
|
||||
v->service_interval = serv_int;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
110
players.c
110
players.c
|
@ -1,3 +1,6 @@
|
|||
/** @file,
|
||||
* sjdlfkasjdf
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "ttd.h"
|
||||
#include "string.h"
|
||||
|
@ -217,7 +220,7 @@ static void SubtractMoneyFromAnyPlayer(Player *p, int32 cost)
|
|||
|
||||
void SubtractMoneyFromPlayer(int32 cost)
|
||||
{
|
||||
uint pid = _current_player;
|
||||
PlayerID pid = _current_player;
|
||||
if (pid < MAX_PLAYERS)
|
||||
SubtractMoneyFromAnyPlayer(DEREF_PLAYER(pid), cost);
|
||||
}
|
||||
|
@ -630,23 +633,36 @@ static void DeletePlayerStuff(int pi)
|
|||
p->president_name_1 = 0;
|
||||
}
|
||||
|
||||
// functionality.
|
||||
// 0 - make new player
|
||||
// 1 - make new AI player
|
||||
// 2 - delete player (p2)
|
||||
// 3 - join player (p1 >> 8) & 0xFF with (p1 >> 16) & 0xFF
|
||||
/** Control the players: add, delete, etc.
|
||||
* @param x,y unused
|
||||
* @param p1 various functionality
|
||||
* - p1 = 0 - create a new player, Which player (network) it will be is in p2
|
||||
* - p1 = 1 - create a new AI player
|
||||
* - p1 = 2 - delete a player. Player is identified by p2
|
||||
* - p1 = 3 - merge two companies together. Player to merge #1 with player #2. Identified by p2
|
||||
* @param p2 various functionality, dictated by p1
|
||||
* - p1 = 0 - ClientID of the newly created player
|
||||
* - p1 = 2 - PlayerID of the that is getting deleted
|
||||
* - p1 = 3 - #1 p2 = (bit 0-15) - player to merge (p2 & 0xFFFF)
|
||||
* - #2 p2 = (bit 16-31) - player to be merged into ((p2>>16)&0xFFFF)
|
||||
* @todo In the case of p1=0, create new player, the clientID of the new player is in parameter
|
||||
* p2. This parameter is passed in at function DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
|
||||
* on the server itself. First of all this is unbelievably ugly; second of all, well,
|
||||
* it IS ugly! <b>Someone fix this up :)</b> So where to fix?@n
|
||||
* @arg - network_server.c:838 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)@n
|
||||
* @arg - network_client.c:536 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP) from where the map has been received
|
||||
*/
|
||||
int32 CmdPlayerCtrl(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int pi;
|
||||
Player *p;
|
||||
if (flags & DC_EXEC) _current_player = OWNER_NONE;
|
||||
|
||||
if (!(flags & DC_EXEC))
|
||||
return 0;
|
||||
switch (p1) {
|
||||
case 0: { /* Create a new player */
|
||||
Player *p;
|
||||
PlayerID pid = p2;
|
||||
|
||||
_current_player = OWNER_NONE;
|
||||
if (!(flags & DC_EXEC) || pid >= MAX_PLAYERS) return 0;
|
||||
|
||||
switch(p1 & 0xff) {
|
||||
case 0: // make new player
|
||||
p = DoStartupNewPlayer(false);
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
|
@ -665,9 +681,9 @@ int32 CmdPlayerCtrl(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
}
|
||||
#ifdef ENABLE_NETWORK
|
||||
if (_network_server) {
|
||||
NetworkClientInfo *ci;
|
||||
// UGLY! p2 is mis-used to fetch the client-id
|
||||
ci = &_network_client_info[p2];
|
||||
/* XXX - UGLY! p2 (pid) is mis-used to fetch the client-id, done at server-side
|
||||
* in network_server.c:838, function DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) */
|
||||
NetworkClientInfo *ci = &_network_client_info[pid];
|
||||
ci->client_playas = p->index + 1;
|
||||
NetworkUpdateClientInfo(ci->client_index);
|
||||
|
||||
|
@ -690,48 +706,62 @@ int32 CmdPlayerCtrl(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
_local_player = player_backup;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_network_server) {
|
||||
NetworkClientInfo *ci;
|
||||
// UGLY! p2 is mis-used to fetch the client-id
|
||||
ci = &_network_client_info[p2];
|
||||
ci->client_playas = OWNER_SPECTATOR;
|
||||
NetworkUpdateClientInfo(ci->client_index);
|
||||
}
|
||||
#endif /* ENABLE_NETWORK */
|
||||
} else if (_network_server) {
|
||||
/* XXX - UGLY! p2 (pid) is mis-used to fetch the client-id, done at server-side
|
||||
* in network_server.c:838, function DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) */
|
||||
NetworkClientInfo *ci = &_network_client_info[pid];
|
||||
ci->client_playas = OWNER_SPECTATOR;
|
||||
NetworkUpdateClientInfo(ci->client_index);
|
||||
}
|
||||
break;
|
||||
case 1: // make new ai player
|
||||
#endif /* ENABLE_NETWORK */
|
||||
} break;
|
||||
|
||||
case 1: /* Make a new AI player */
|
||||
if (!(flags & DC_EXEC)) return 0;
|
||||
|
||||
DoStartupNewPlayer(true);
|
||||
break;
|
||||
case 2: // delete player
|
||||
|
||||
case 2: { /* Delete a player */
|
||||
Player *p;
|
||||
|
||||
if (p2 >= MAX_PLAYERS) return CMD_ERROR;
|
||||
|
||||
if (!(flags & DC_EXEC)) return 0;
|
||||
|
||||
p = DEREF_PLAYER(p2);
|
||||
|
||||
/* Only allow removal of HUMAN companies */
|
||||
if (IS_HUMAN_PLAYER(p2)) {
|
||||
if (IS_HUMAN_PLAYER(p->index)) {
|
||||
/* Delete any open window of the company */
|
||||
DeletePlayerWindows(p2);
|
||||
DeletePlayerWindows(p->index);
|
||||
|
||||
/* Show the bankrupt news */
|
||||
SetDParam(0, p->name_1);
|
||||
SetDParam(1, p->name_2);
|
||||
AddNewsItem( (StringID)(p2 + 16*3), NEWS_FLAGS(NM_CALLBACK, 0, NT_COMPANY_INFO, DNC_BANKRUPCY),0,0);
|
||||
AddNewsItem( (StringID)(p->index + 16*3), NEWS_FLAGS(NM_CALLBACK, 0, NT_COMPANY_INFO, DNC_BANKRUPCY),0,0);
|
||||
|
||||
/* Remove the company */
|
||||
ChangeOwnershipOfPlayerItems(p2, 255);
|
||||
p->money64 = p->player_money = 100000000;
|
||||
ChangeOwnershipOfPlayerItems(p->index, OWNER_SPECTATOR);
|
||||
p->money64 = p->player_money = 100000000; // XXX - wtf?
|
||||
p->is_active = false;
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case 3: // join player
|
||||
pi = (byte)(p1 >> 8);
|
||||
ChangeOwnershipOfPlayerItems(pi, (byte)(p1 >> 16));
|
||||
DeletePlayerStuff(pi);
|
||||
break;
|
||||
case 3: { /* Merge a company (#1) into another company (#2), elimination company #1 */
|
||||
PlayerID pid_old = p2 & 0xFFFF;
|
||||
PlayerID pid_new = (p2 >> 16) & 0xFFFF;
|
||||
|
||||
if (pid_old >= MAX_PLAYERS || pid_new >= MAX_PLAYERS) return CMD_ERROR;
|
||||
|
||||
if (!(flags & DC_EXEC)) return CMD_ERROR;
|
||||
|
||||
ChangeOwnershipOfPlayerItems(pid_old, pid_new);
|
||||
DeletePlayerStuff(pid_old);
|
||||
} break;
|
||||
default: return CMD_ERROR;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
76
rail_cmd.c
76
rail_cmd.c
|
@ -555,8 +555,8 @@ static int32 ValidateAutoDrag(byte *railbit, int x, int y, int ex, int ey)
|
|||
// validate the direction
|
||||
while (((trdx <= 0) && (dx > 0)) || ((trdx >= 0) && (dx < 0)) ||
|
||||
((trdy <= 0) && (dy > 0)) || ((trdy >= 0) && (dy < 0))) {
|
||||
if (*railbit < 8) { // first direction is invalid, try the other
|
||||
SETBIT(*railbit, 3);
|
||||
if (!HASBIT(*railbit, 3)) { // first direction is invalid, try the other
|
||||
SETBIT(*railbit, 3); // reverse the direction
|
||||
trdx = -trdx;
|
||||
trdy = -trdy;
|
||||
} else // other direction is invalid too, invalid drag
|
||||
|
@ -625,11 +625,19 @@ static int32 CmdRailTrackHelper(int x, int y, uint32 flags, uint32 p1, uint32 p2
|
|||
return (total_cost == 0) ? CMD_ERROR : total_cost;
|
||||
}
|
||||
|
||||
/** Build rail on a stretch of track.
|
||||
* Stub for the unified rail builder/remover
|
||||
* @see CmdRailTrackHelper
|
||||
*/
|
||||
int32 CmdBuildRailroadTrack(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
return CmdRailTrackHelper(x, y, flags, p1, CLRBIT(p2, 7));
|
||||
}
|
||||
|
||||
/** Build rail on a stretch of track.
|
||||
* Stub for the unified rail builder/remover
|
||||
* @see CmdRailTrackHelper
|
||||
*/
|
||||
int32 CmdRemoveRailroadTrack(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
return CmdRailTrackHelper(x, y, flags, p1, SETBIT(p2, 7));
|
||||
|
@ -813,36 +821,42 @@ int32 CmdBuildSingleSignal(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
return cost;
|
||||
}
|
||||
|
||||
/* Build many signals by dragging: AutoSignals
|
||||
* x,y = start tile
|
||||
* p1 = end tile
|
||||
* p2 = (bit 0) - 0 = build, 1 = remove signals
|
||||
* p2 = (bit 3) - 0 = signals, 1 = semaphores
|
||||
* p2 = (bit 4-6) - track-orientation, valid values: 0-5
|
||||
* p2 = (bit 24-31) - user defined signals_density
|
||||
/** Build many signals by dragging; AutoSignals
|
||||
* @param x,y start tile of drag
|
||||
* @param p1 end tile of drag
|
||||
* @param p2 various bitstuffed elements
|
||||
* - p2 = (bit 0) - 0 = build, 1 = remove signals
|
||||
* - p2 = (bit 3) - 0 = signals, 1 = semaphores
|
||||
* - p2 = (bit 4- 6) - track-orientation, valid values: 0-5
|
||||
* - p2 = (bit 24-31) - user defined signals_density
|
||||
*/
|
||||
static int32 CmdSignalTrackHelper(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int ex, ey;
|
||||
byte railbit = (p2 >> 4) & 7;
|
||||
bool error = true;
|
||||
TileIndex tile = TILE_FROM_XY(x, y);
|
||||
int32 ret, total_cost, signal_ctr;
|
||||
byte m5, semaphores = (HASBIT(p2, 3)) ? 8 : 0;
|
||||
byte m5, signals;
|
||||
TileIndex tile = TILE_FROM_XY(x, y);
|
||||
bool error = true;
|
||||
|
||||
int mode = p2 & 0x1;
|
||||
// for vertical/horizontal tracks, double the given signals density
|
||||
// since the original amount will be too dense (shorter tracks)
|
||||
byte signal_density = (railbit & 0x6) ? (p2 >> 24) * 2: (p2 >> 24);
|
||||
byte signals;
|
||||
byte semaphores = (HASBIT(p2, 3)) ? 8 : 0;
|
||||
byte railbit = (p2 >> 4) & 0x7;
|
||||
byte signal_density = (p2 >> 24);
|
||||
|
||||
if (p1 > MapSize()) return CMD_ERROR;
|
||||
if (signal_density == 0 || signal_density > 20) return CMD_ERROR;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
/* for vertical/horizontal tracks, double the given signals density
|
||||
* since the original amount will be too dense (shorter tracks) */
|
||||
if (railbit & 0x6) signal_density *= 2;
|
||||
|
||||
// unpack end tile
|
||||
ex = TileX(p1) * 16;
|
||||
ey = TileY(p1) * 16;
|
||||
|
||||
if (ValidateAutoDrag(&railbit, x, y, ex, ey) == CMD_ERROR)
|
||||
return CMD_ERROR;
|
||||
if (CmdFailed(ValidateAutoDrag(&railbit, x, y, ex, ey))) return CMD_ERROR;
|
||||
|
||||
// copy the signal-style of the first rail-piece if existing
|
||||
m5 = _map5[tile];
|
||||
|
@ -851,9 +865,8 @@ static int32 CmdSignalTrackHelper(int x, int y, uint32 flags, uint32 p1, uint32
|
|||
if (signals == 0) signals = _signals_table_both[railbit];
|
||||
|
||||
semaphores = (_map3_hi[tile] & ~3) ? 8 : 0; // copy signal/semaphores style (independent of CTRL)
|
||||
} else { // no signals exist, drag a two-way signal stretch
|
||||
} else // no signals exist, drag a two-way signal stretch
|
||||
signals = _signals_table_both[railbit];
|
||||
}
|
||||
|
||||
/* signal_density_ctr - amount of tiles already processed
|
||||
* signals_density - patch setting to put signal on every Nth tile (double space on |, -- tracks)
|
||||
|
@ -864,25 +877,22 @@ static int32 CmdSignalTrackHelper(int x, int y, uint32 flags, uint32 p1, uint32
|
|||
and convert all others to semaphore/signal
|
||||
* mode - 1 remove signals, 0 build signals */
|
||||
signal_ctr = total_cost = 0;
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
// only build/remove signals with the specified density
|
||||
if ((signal_ctr % signal_density) == 0 ) {
|
||||
ret = DoCommand(x, y, (railbit & 7) | semaphores, signals, flags, (mode == 1) ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
|
||||
|
||||
/* Abort placement for any other error than NOT_SUITABLE_TRACK
|
||||
* This includes vehicles on track, competitor's tracks, etc. */
|
||||
if (ret == CMD_ERROR) {
|
||||
if (_error_message != STR_1005_NO_SUITABLE_RAILROAD_TRACK && mode != 1) {
|
||||
return CMD_ERROR;
|
||||
}
|
||||
if (CmdFailed(ret)) {
|
||||
if (_error_message != STR_1005_NO_SUITABLE_RAILROAD_TRACK && mode != 1) return CMD_ERROR;
|
||||
} else {
|
||||
error = false;
|
||||
total_cost += ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (ex == x && ey == y) // reached end of drag
|
||||
break;
|
||||
if (ex == x && ey == y) break; // reached end of drag
|
||||
|
||||
x += _railbit.xinc[railbit];
|
||||
y += _railbit.yinc[railbit];
|
||||
|
@ -895,7 +905,10 @@ static int32 CmdSignalTrackHelper(int x, int y, uint32 flags, uint32 p1, uint32
|
|||
return (error) ? CMD_ERROR : total_cost;
|
||||
}
|
||||
|
||||
/* Stub for the unified Signal builder/remover */
|
||||
/** Build signals on a stretch of track.
|
||||
* Stub for the unified signal builder/remover
|
||||
* @see CmdSignalTrackHelper
|
||||
*/
|
||||
int32 CmdBuildSignalTrack(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
return CmdSignalTrackHelper(x, y, flags, p1, p2);
|
||||
|
@ -941,7 +954,10 @@ int32 CmdRemoveSingleSignal(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
return _price.remove_signals;
|
||||
}
|
||||
|
||||
/* Stub for the unified Signal builder/remover */
|
||||
/** Remove signals on a stretch of track.
|
||||
* Stub for the unified signal builder/remover
|
||||
* @see CmdSignalTrackHelper
|
||||
*/
|
||||
int32 CmdRemoveSignalTrack(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
return CmdSignalTrackHelper(x, y, flags, p1, SETBIT(p2, 0));
|
||||
|
|
|
@ -1017,19 +1017,21 @@ static void PatchesSelectionWndProc(Window *w, WindowEvent *e)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Network-safe changing of patch-settings.
|
||||
* @param p1 bytes 0 - 7: the patches type (page) that is being changed (construction, network, ai)
|
||||
* @param p1 bytes 8 - ..: the actual patch (entry) being set inside the category
|
||||
/** Network-safe changing of patch-settings.
|
||||
* @param p1 various bitstuffed elements
|
||||
* - p1 = (bit 0- 7) - the patches type (page) that is being changed (construction, network, ai) (p1 & 0xFF)
|
||||
* - p2 = (bit 8-15) - the actual patch (entry) being set inside the category ((p1>>8) & 0xFF)
|
||||
* @param p2 the new value for the patch
|
||||
* @todo check that the new value is a valid one. Awful lot of work, but since only
|
||||
* the server is allowed to do this, we trust it on this one :)
|
||||
*/
|
||||
int32 CmdChangePatchSetting(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
byte pcat = p1 & 0xFF;
|
||||
byte pel = (p1 >> 8) & 0xFF;
|
||||
|
||||
if (pcat >= lengthof(_patches_page)) return 0;
|
||||
if (pel >= _patches_page[pcat].num) return 0;
|
||||
if (pcat >= lengthof(_patches_page)) return CMD_ERROR;
|
||||
if (pel >= _patches_page[pcat].num) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
const PatchEntry *pe = &_patches_page[pcat].entries[pel];
|
||||
|
|
186
unmovable_cmd.c
186
unmovable_cmd.c
|
@ -12,6 +12,94 @@
|
|||
#include "town.h"
|
||||
#include "sprite.h"
|
||||
|
||||
/** Destroy a HQ.
|
||||
* During normal gameplay you can only implicitely destroy a HQ when you are
|
||||
* rebuilding it. Otherwise, only water can destroy it.
|
||||
* @param tile tile coordinates where HQ is located to destroy
|
||||
* @param flags docommand flags of calling function
|
||||
*/
|
||||
int32 DestroyCompanyHQ(TileIndex tile, uint32 flags)
|
||||
{
|
||||
Player *p;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_PROPERTY);
|
||||
|
||||
/* Find player that has HQ flooded, and reset their location_of_house */
|
||||
if (_current_player == OWNER_WATER) {
|
||||
bool dodelete = false;
|
||||
|
||||
FOR_ALL_PLAYERS(p) {
|
||||
if (p->location_of_house == tile) {
|
||||
dodelete = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dodelete) return CMD_ERROR;
|
||||
} else /* Destruction was initiated by player */
|
||||
p = DEREF_PLAYER(_current_player);
|
||||
|
||||
if (p->location_of_house == 0) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
DoClearSquare(p->location_of_house + TILE_XY(0,0));
|
||||
DoClearSquare(p->location_of_house + TILE_XY(0,1));
|
||||
DoClearSquare(p->location_of_house + TILE_XY(1,0));
|
||||
DoClearSquare(p->location_of_house + TILE_XY(1,1));
|
||||
p->location_of_house = 0; // reset HQ position
|
||||
InvalidateWindow(WC_COMPANY, (int)p->index);
|
||||
}
|
||||
|
||||
// cost of relocating company is 1% of company value
|
||||
return CalculateCompanyValue(p) / 100;
|
||||
}
|
||||
|
||||
/** Build or relocate the HQ. This depends if the HQ is already built or not
|
||||
* @param x,y the coordinates where the HQ will be built or relocated to
|
||||
* @param p1 relocate HQ (set to some value, usually 1 or true)
|
||||
* @param p2 unused
|
||||
*/
|
||||
extern int32 CheckFlatLandBelow(uint tile, uint w, uint h, uint flags, uint invalid_dirs, int *);
|
||||
int32 CmdBuildCompanyHQ(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TileIndex tile = TILE_FROM_XY(x,y);
|
||||
Player *p = DEREF_PLAYER(_current_player);
|
||||
int cost;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_PROPERTY);
|
||||
|
||||
cost = CheckFlatLandBelow(tile, 2, 2, flags, 0, NULL);
|
||||
if (CmdFailed(cost)) return CMD_ERROR;
|
||||
|
||||
if (p1) { /* Moving HQ */
|
||||
int32 ret;
|
||||
|
||||
if (p->location_of_house == 0) return CMD_ERROR;
|
||||
|
||||
ret = DestroyCompanyHQ(p->location_of_house, flags);
|
||||
|
||||
if (CmdFailed(ret)) return CMD_ERROR;
|
||||
|
||||
cost += ret;
|
||||
} else { /* Building new HQ */
|
||||
if (p->location_of_house != 0) return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
int score = UpdateCompanyRatingAndValue(p, false);
|
||||
|
||||
p->location_of_house = tile;
|
||||
|
||||
ModifyTile(tile + TILE_XY(0,0), MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, 0x80);
|
||||
ModifyTile(tile + TILE_XY(0,1), MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, 0x81);
|
||||
ModifyTile(tile + TILE_XY(1,0), MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, 0x82);
|
||||
ModifyTile(tile + TILE_XY(1,1), MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, 0x83);
|
||||
UpdatePlayerHouse(p, score);
|
||||
InvalidateWindow(WC_COMPANY, (int)p->index);
|
||||
}
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
typedef struct DrawTileUnmovableStruct {
|
||||
uint16 image;
|
||||
byte subcoord_x;
|
||||
|
@ -110,8 +198,7 @@ static int32 ClearTile_Unmovable(uint tile, byte flags)
|
|||
byte m5 = _map5[tile];
|
||||
|
||||
if (m5 & 0x80) {
|
||||
if (_current_player == OWNER_WATER)
|
||||
return DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_DESTROY_COMPANY_HQ);
|
||||
if (_current_player == OWNER_WATER) return DestroyCompanyHQ(tile, DC_EXEC);
|
||||
return_cmd_error(STR_5804_COMPANY_HEADQUARTERS_IN);
|
||||
}
|
||||
|
||||
|
@ -307,101 +394,6 @@ restart:
|
|||
} while (--i);
|
||||
}
|
||||
|
||||
extern int32 CheckFlatLandBelow(uint tile, uint w, uint h, uint flags, uint invalid_dirs, int *);
|
||||
|
||||
/** Build or relocate the HQ. This depends if the HQ is already built or not
|
||||
* @param x,y the coordinates where the HQ will be built or relocated to
|
||||
* @param p1 relocate HQ (set to some value, usually 1 or true)
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdBuildCompanyHQ(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TileIndex tile = TILE_FROM_XY(x,y);
|
||||
Player *p = DEREF_PLAYER(_current_player);
|
||||
int cost;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_PROPERTY);
|
||||
|
||||
cost = CheckFlatLandBelow(tile, 2, 2, flags, 0, NULL);
|
||||
if (CmdFailed(cost)) return CMD_ERROR;
|
||||
|
||||
if (p1) { /* Moving HQ */
|
||||
int32 ret;
|
||||
|
||||
if (p->location_of_house == 0) return CMD_ERROR;
|
||||
|
||||
ret = DoCommandByTile(p->location_of_house, 0, 0, flags, CMD_DESTROY_COMPANY_HQ);
|
||||
|
||||
if (CmdFailed(ret)) return CMD_ERROR;
|
||||
|
||||
cost += ret;
|
||||
} else { /* Building new HQ */
|
||||
if (p->location_of_house != 0) return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
int score = UpdateCompanyRatingAndValue(p, false);
|
||||
|
||||
p->location_of_house = tile;
|
||||
|
||||
ModifyTile(tile + TILE_XY(0,0), MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, 0x80);
|
||||
ModifyTile(tile + TILE_XY(0,1), MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, 0x81);
|
||||
ModifyTile(tile + TILE_XY(1,0), MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, 0x82);
|
||||
ModifyTile(tile + TILE_XY(1,1), MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, 0x83);
|
||||
UpdatePlayerHouse(p, score);
|
||||
InvalidateWindow(WC_COMPANY, (int)p->index);
|
||||
}
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
/** Destroy a HQ.
|
||||
* During normal gameplay you can only implicitely destroy a HQ when you are
|
||||
* rebuilding it. Otherwise, only water can destroy it. Unfortunately there is
|
||||
* no safeguard against a hacked client to call this command, unless we also add
|
||||
* flags to the command table which commands can be called directly and which not.
|
||||
* @param x,y tile coordinates where HQ is located to destroy
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdDestroyCompanyHQ(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
TileIndex tile;
|
||||
Player *p;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_PROPERTY);
|
||||
|
||||
/* Find player that has HQ flooded, and reset their location_of_house */
|
||||
if (_current_player == OWNER_WATER) {
|
||||
bool dodelete = false;
|
||||
tile = TILE_FROM_XY(x,y);
|
||||
|
||||
FOR_ALL_PLAYERS(p) {
|
||||
if (p->location_of_house == tile) {
|
||||
dodelete = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dodelete) return CMD_ERROR;
|
||||
} else /* Destruction was initiated by player */
|
||||
p = DEREF_PLAYER(_current_player);
|
||||
|
||||
if (p->location_of_house == 0) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
DoClearSquare(p->location_of_house + TILE_XY(0,0));
|
||||
DoClearSquare(p->location_of_house + TILE_XY(0,1));
|
||||
DoClearSquare(p->location_of_house + TILE_XY(1,0));
|
||||
DoClearSquare(p->location_of_house + TILE_XY(1,1));
|
||||
p->location_of_house = 0; // reset HQ position
|
||||
InvalidateWindow(WC_COMPANY, (int)p->index);
|
||||
}
|
||||
|
||||
// cost of relocating company is 1% of company value
|
||||
return CalculateCompanyValue(p) / 100;
|
||||
}
|
||||
|
||||
|
||||
static void ChangeTileOwner_Unmovable(uint tile, byte old_player, byte new_player)
|
||||
{
|
||||
if (_map_owner[tile] != old_player)
|
||||
|
|
29
vehicle.c
29
vehicle.c
|
@ -1306,9 +1306,13 @@ extern int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p
|
|||
extern int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2);
|
||||
extern int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2);
|
||||
|
||||
/* Replaces a vehicle (used to be called autorenew)
|
||||
p1 - Index of vehicle
|
||||
p2 - Type of new engine */
|
||||
/** Replaces a vehicle (used to be called autorenew).
|
||||
* @param x,y unused
|
||||
* @param p1 index of vehicle being replaced
|
||||
* @param p2 various bitstuffed elements
|
||||
* - p2 = (bit 0-15) - new engine type for the vehicle (p2 & 0xFFFF)
|
||||
* - p2 = (bit 16-31) - money the player wants to have left after replacement counted in 100.000 (100K) (p2 >> 16)
|
||||
*/
|
||||
int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
/* makesvariables to inform about how much money the player wants to have left after replacing
|
||||
|
@ -1317,11 +1321,11 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
This way the max is 6553 millions and it is more than the 32 bit that is stored in _patches
|
||||
This is a nice way to send 32 bit and only use 16 bit
|
||||
the last 8 bit is the engine. The 8 bits in front of the engine is free so it have room for 16 bit engine entries */
|
||||
uint16 new_engine_type = (uint16)(p2 & 0xFFFF);
|
||||
uint32 autorefit_money = (p2 >> 16) * 100000;
|
||||
EngineID new_engine_type = (p2 & 0xFFFF);
|
||||
uint32 autorefit_money = (p2 >> 16) * 100000;
|
||||
Vehicle *v, *u, *first;
|
||||
int cost, build_cost, rear_engine_cost = 0;
|
||||
byte old_engine_type;
|
||||
EngineID old_engine_type;
|
||||
|
||||
if (!IsVehicleIndex(p1)) return CMD_ERROR;
|
||||
|
||||
|
@ -1329,9 +1333,9 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
|
||||
old_engine_type = v->engine_type;
|
||||
|
||||
// first we make sure that it's a valid type the user requested
|
||||
// check that it's an engine that is in the engine array
|
||||
if (new_engine_type >= TOTAL_NUM_ENGINES ) return CMD_ERROR;
|
||||
/* First we make sure that it's a valid type the user requested
|
||||
* check that it's an engine that is in the engine array */
|
||||
if (!IsEngineIndex(new_engine_type)) return CMD_ERROR;
|
||||
|
||||
// check that the new vehicle type is the same as the original one
|
||||
if (v->type != DEREF_ENGINE(new_engine_type)->type) return CMD_ERROR;
|
||||
|
@ -1357,8 +1361,7 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
|
||||
/* In a rare situation, when 2 clients are connected to 1 company and have the same
|
||||
settings, a vehicle can be replaced twice.. check if this is the situation here */
|
||||
if (old_engine_type == new_engine_type && v->age == 0)
|
||||
return CMD_ERROR;
|
||||
if (old_engine_type == new_engine_type && v->age == 0) return CMD_ERROR;
|
||||
|
||||
if ( v->type == VEH_Train ) {
|
||||
first = GetFirstVehicleInChain(v);
|
||||
|
@ -1415,8 +1418,7 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
|
||||
if (flags & DC_EXEC) {
|
||||
/* We do not really buy a new vehicle, we upgrade the old one */
|
||||
Engine *e;
|
||||
e = DEREF_ENGINE(new_engine_type);
|
||||
Engine *e = DEREF_ENGINE(new_engine_type);
|
||||
|
||||
v->reliability = e->reliability;
|
||||
v->reliability_spd_dec = e->reliability_spd_dec;
|
||||
|
@ -1427,7 +1429,6 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
|
||||
v->value = build_cost;
|
||||
|
||||
|
||||
if (v->engine_type != new_engine_type) {
|
||||
byte sprite = v->spritenum;
|
||||
byte cargo_type = v->cargo_type;
|
||||
|
|
|
@ -55,7 +55,7 @@ typedef struct VehicleRail {
|
|||
|
||||
// NOSAVE: for wagon override - id of the first engine in train
|
||||
// 0xffff == not in train
|
||||
uint16 first_engine;
|
||||
EngineID first_engine;
|
||||
|
||||
byte track;
|
||||
byte force_proceed;
|
||||
|
|
61
water_cmd.c
61
water_cmd.c
|
@ -159,30 +159,44 @@ static void MarkTilesAroundDirty(uint tile)
|
|||
MarkTileDirtyByTile(TILE_ADDXY(tile, -1, 0));
|
||||
}
|
||||
|
||||
/** Builds a lock (ship-lift)
|
||||
* @param x,y tile coordinates where to place the lock
|
||||
* @param p1 unused
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdBuildLock(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
uint tile = TILE_FROM_XY(x,y);
|
||||
int32 ret;
|
||||
uint th;
|
||||
TileIndex tile = TILE_FROM_XY(x,y);
|
||||
uint tileh;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
th = GetTileSlope(tile, NULL);
|
||||
tileh = GetTileSlope(tile, NULL);
|
||||
|
||||
if (th==3 || th==6 || th==9 || th==12) {
|
||||
static const byte _shiplift_dirs[16] = {0,0,0,2,0,0,1,0,0,3,0,0,0};
|
||||
ret = DoBuildShiplift(tile, _shiplift_dirs[th], flags);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
|
||||
if (tileh == 3 || tileh == 6 || tileh == 9 || tileh == 12) {
|
||||
static const byte _shiplift_dirs[16] = {0, 0, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 0};
|
||||
return DoBuildShiplift(tile, _shiplift_dirs[tileh], flags);
|
||||
}
|
||||
|
||||
return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
|
||||
}
|
||||
|
||||
/** Build a piece of canal.
|
||||
* @param x,y end tile of stretch-dragging
|
||||
* @param p1 start tile of stretch-dragging
|
||||
* @param p2 unused
|
||||
*/
|
||||
int32 CmdBuildCanal(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int32 ret, cost;
|
||||
int size_x, size_y;
|
||||
int sx = TileX((TileIndex)p1);
|
||||
int sy = TileY((TileIndex)p1);
|
||||
int sx, sy;
|
||||
|
||||
if (p1 > MapSize()) return CMD_ERROR;
|
||||
|
||||
sx = TileX(p1);
|
||||
sy = TileY(p1);
|
||||
/* x,y are in pixel-coordinates, transform to tile-coordinates
|
||||
* to be able to use the BEGIN_TILE_LOOP() macro */
|
||||
x >>= 4; y >>= 4;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
@ -192,11 +206,13 @@ int32 CmdBuildCanal(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
size_x = (x - sx) + 1;
|
||||
size_y = (y - sy) + 1;
|
||||
|
||||
/* Outside the editor you can only drag canals, and not areas */
|
||||
if (_game_mode != GM_EDITOR && (sx != x && sy != y)) return CMD_ERROR;
|
||||
|
||||
cost = 0;
|
||||
BEGIN_TILE_LOOP(tile, size_x, size_y, TILE_XY(sx, sy)) {
|
||||
ret = 0;
|
||||
if (GetTileSlope(tile, NULL) != 0)
|
||||
return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
|
||||
if (GetTileSlope(tile, NULL) != 0) return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
|
||||
|
||||
// can't make water of water!
|
||||
if (IsTileType(tile, MP_WATER)) {
|
||||
|
@ -204,19 +220,16 @@ int32 CmdBuildCanal(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
} else {
|
||||
/* is middle piece of a bridge? */
|
||||
if (IsTileType(tile, MP_TUNNELBRIDGE) && _map5[tile] & 0x40) { /* build under bridge */
|
||||
if (_map5[tile] & 0x20) { // transport route under bridge
|
||||
_error_message = STR_5800_OBJECT_IN_THE_WAY;
|
||||
ret = CMD_ERROR;
|
||||
}
|
||||
else if (_map5[tile] & 0x18) { // already water under bridge
|
||||
_error_message = STR_1007_ALREADY_BUILT;
|
||||
ret = CMD_ERROR;
|
||||
}
|
||||
if (_map5[tile] & 0x20) // transport route under bridge
|
||||
return_cmd_error(STR_5800_OBJECT_IN_THE_WAY);
|
||||
|
||||
if (_map5[tile] & 0x18) // already water under bridge
|
||||
return_cmd_error(STR_1007_ALREADY_BUILT);
|
||||
/* no bridge? then try to clear it. */
|
||||
} else
|
||||
ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
|
||||
if (ret == CMD_ERROR) return ret;
|
||||
if (CmdFailed(ret)) return CMD_ERROR;
|
||||
cost += ret;
|
||||
|
||||
/* execute modifications */
|
||||
|
|
Loading…
Reference in New Issue