13 #include "../api_param.h" 14 #include "../api_class.h" 15 #include "../api_function.h" 16 #include "../../builder/brueckenbauer.h" 17 #include "../../ground/grund.h" 18 #include "../../tool/simtool.h" 19 #include "../../world/simworld.h" 20 #include "../../dataobj/environment.h" 21 #include "../../script/script.h" 22 #include "../../descriptor/bridge_desc.h" 23 #include "../../descriptor/building_desc.h" 24 #include "../../descriptor/roadsign_desc.h" 25 #include "../../descriptor/way_obj_desc.h" 29 using namespace script_api;
32 SQInteger command_constructor(HSQUIRRELVM vm)
35 uint16
id = param<uint16>::get(vm, 2);
37 if (
id & GENERAL_TOOL) {
40 if (
id == (TOOL_EXEC_TWO_CLICK_SCRIPT | GENERAL_TOOL)) {
45 if (tool_t *tool = create_tool(
id)) {
46 my_tool_t* mtool =
new my_tool_t(tool);
47 attach_instance(vm, 1, mtool);
52 return sq_raise_error(vm,
"Invalid tool called (%d / 0x%x)",
id & 0xfff,
id);
56 SQInteger param<call_tool_init>::push(HSQUIRRELVM vm, call_tool_init v)
59 return sq_raise_error(vm, *v.error ? v.error :
"Strange error occurred");
62 std::unique_ptr<tool_t> our_tool;
63 tool_t *tool = v.tool;
65 our_tool.reset(v.create_tool());
66 tool = our_tool.get();
69 return sq_raise_error(vm,
"Called null tool");
72 tool->flags &= (tool_t::WFL_SHIFT | tool_t:: WFL_CTRL);
73 tool->flags |= tool_t::WFL_SCRIPT;
75 player_t *player = get_my_player(vm);
79 tool->flags |= tool_t::WFL_NO_CHK;
84 return sq_raise_error(vm,
"Called tool with player == null");
89 if (
const char* blocker = env_t::networkmode ? sq_get_suspend_blocker(vm) : NULL) {
90 return sq_raise_error(vm,
"Cannot call this tool from within `%s'.", blocker);
94 uint32 callback_id = suspended_scripts_t::get_unique_key(tool);
95 tool->callback_id = callback_id;
99 welt->set_tool_api(tool, player, suspended);
102 if (suspended && !v.no_block) {
104 suspended_scripts_t::register_suspended_script(callback_id, vm);
106 return sq_suspendvm(vm);
110 return param<bool>::push(vm, res);
115 call_tool_init script_api::command_rename(player_t *owner,
char what, koord3d pos,
const char* name)
119 buf.printf(
"%c%s,%s", what, pos.get_str(), name);
122 uint16 tool_id = name ? TOOL_RENAME | SIMPLE_TOOL : 0;
124 return call_tool_init(tool_id, (
const char*)buf, 0, owner);
127 call_tool_init script_api::command_rename(player_t *owner,
char what, uint32
id,
const char* name)
131 buf.printf(
"%c%u,%s", what,
id, name);
134 uint16 tool_id = name ? TOOL_RENAME | SIMPLE_TOOL : 0;
136 return call_tool_init(tool_id, (
const char*)buf, 0, owner);
140 SQInteger command_work(HSQUIRRELVM vm)
142 tool_t *tool = param<tool_t*>::get(vm, 1);
144 player_t *player = param<player_t*>::get(vm, 2);
146 koord3d pos1 = param<koord3d>::get(vm, 3);
148 SQInteger top = sq_gettop(vm);
154 const char* default_param = top>3 ? param<const char*>::get(vm, top) : NULL;
155 koord3d pos2 = top>4 ? param<koord3d>::get(vm, 4) : koord3d::invalid;
157 bool twoclick = top>4;
160 my_tool_t *mtool = get_attached_instance<my_tool_t>(vm, 1, param<tool_t*>::tag());
162 return sq_raise_error(vm,
"Called from an instance different to tool_x");
164 plainstring &pdefault_param = mtool->default_param;
165 pdefault_param = default_param;
166 tool->set_default_param( (
const char*)pdefault_param );
169 return param<call_tool_work>::push(vm, call_tool_work(tool, player, pos1));
172 return param<call_tool_work>::push(vm, call_tool_work(tool, player, pos1, pos2));
176 tool_t * call_tool_base_t::create_tool()
178 tool_t *tool = ::create_tool(tool_id);
180 tool->set_default_param(default_param);
187 SQInteger param<call_tool_work>::push(HSQUIRRELVM vm, call_tool_work v)
192 return param<const char*>::push(vm, v.error);
195 return sq_raise_error(vm, *v.error ? v.error :
"Strange error occurred");
199 std::unique_ptr<tool_t> our_tool;
200 tool_t *tool = v.tool;
202 our_tool.reset(v.create_tool());
203 tool = our_tool.get();
206 return sq_raise_error(vm,
"Called null tool");
209 tool->flags &= (tool_t::WFL_SHIFT | tool_t:: WFL_CTRL);
210 tool->flags |= tool_t::WFL_SCRIPT;
212 player_t *player = get_my_player(vm);
213 if (player == NULL) {
216 tool->flags |= tool_t::WFL_NO_CHK;
220 if (player == NULL) {
221 return sq_raise_error(vm,
"Called tool with player == null");
224 uint8 flags = tool->flags;
227 if (!tool->is_init_keeps_game_state()) {
228 return sq_raise_error(vm,
"Initializing tool has side effects");
230 if (!tool->init(player)) {
231 return sq_raise_error(vm,
"Error during initializing tool");
236 if (tool->is_work_keeps_game_state() || (!v.twoclick && tool->is_work_here_keeps_game_state(player, v.start))) {
237 return sq_raise_error(vm,
"Tool has no effects");
241 if (dynamic_cast<two_click_tool_t*>(tool)==NULL) {
242 return sq_raise_error(vm,
"Cannot call this tool with two coordinates");
244 if (!tool->is_work_here_keeps_game_state(player, v.start)) {
245 return sq_raise_error(vm,
"First click has side effects");
250 if (
const char* blocker = env_t::networkmode ? sq_get_suspend_blocker(vm) : NULL) {
251 return sq_raise_error(vm,
"Cannot call this tool from within `%s'.", blocker);
255 bool suspended =
false;
256 const char* err = NULL;
260 err = welt->call_work_api(tool, player, v.start, suspended);
266 uint32 callback_id = suspended_scripts_t::get_unique_key(tool);
267 tool->callback_id = callback_id;
268 err = welt->call_work_api(tool, player, v.twoclick ? v.end : v.start, suspended);
270 if (suspended && !v.no_block) {
272 suspended_scripts_t::register_suspended_script(callback_id, vm);
274 return sq_suspendvm(vm);
278 return param<const char*>::push(vm, err);
282 uint8 get_flags(tool_t *tool)
284 return tool->flags & (tool_t::WFL_SHIFT | tool_t:: WFL_CTRL);
288 void set_flags(tool_t *tool, uint8 flags)
290 tool->flags = flags & (tool_t::WFL_SHIFT | tool_t:: WFL_CTRL);
294 void* script_api::param<tool_t*>::tag()
296 return (
void*)param<tool_t*>::get;
300 const char* is_available(
const obj_desc_timelined_t* desc)
302 return desc->is_available(welt->get_timeline_year_month()) ? NULL :
"Object not available (retired or future).";
306 call_tool_work build_way(player_t* pl, koord3d
start, koord3d end,
const way_desc_t* way,
bool straight,
bool keep_city_roads)
309 return call_tool_work(
"No way provided");
311 if (
const char* err = is_available(way)) {
312 return call_tool_work(err);
314 return call_tool_work(TOOL_BUILD_WAY | GENERAL_TOOL, way->get_name(), (straight ? 2 : 0) + (keep_city_roads ? 1 : 0), pl,
start, end);
318 call_tool_work build_wayobj(player_t* pl, koord3d start, koord3d end,
const way_obj_desc_t* wayobj)
320 if (wayobj == NULL) {
321 return call_tool_work(
"No wayobj provided");
323 if (
const char* err = is_available(wayobj)) {
324 return call_tool_work(err);
326 return call_tool_work(TOOL_BUILD_WAYOBJ | GENERAL_TOOL, wayobj->get_name(), 0, pl,
start, end);
330 typedef call_tool_work(*bsr_type)(player_t*, koord3d,
const building_desc_t*, sint16);
332 call_tool_work build_station_rotation(player_t* pl, koord3d pos,
const building_desc_t* building, sint16 layout)
335 if (building == NULL || !building->is_transport_building()) {
336 return call_tool_work(
"No building provided");
338 if (
const char* err = is_available(building)) {
339 return call_tool_work(err);
341 static cbuffer_t buf;
344 uint8 rotation = welt->get_settings().get_rotation();
347 if (building->get_all_layouts() <= 4) {
348 layout = (layout + 4 - rotation) & (building->get_all_layouts() - 1);
350 else for (uint8 i = 0; i < rotation; i++) {
352 static uint8 layout_rotate[16] = { 1, 8, 5, 10, 3, 12, 7, 14, 9, 0, 13, 2, 11, 4, 15, 6 };
354 layout = layout_rotate[layout] & (building->get_all_layouts()-1);
357 buf.printf(
"%s,%i", building->get_name(), layout);
360 buf.printf(
"%s", building->get_name());
362 return call_tool_work(TOOL_BUILD_STATION | GENERAL_TOOL, buf, 0, pl, pos);
365 SQInteger command_build_station(HSQUIRRELVM vm)
372 if (sq_gettop(vm) == 4) {
374 sq_pushinteger(vm, -1);
376 return embed_call_t<bsr_type>::call_function(vm, build_station_rotation,
false);
380 call_tool_work build_depot(player_t* pl, koord3d pos,
const building_desc_t* building)
382 if (building == NULL || !building->is_depot()) {
383 return call_tool_work(
"No depot provided");
385 if (
const char* err = is_available(building)) {
386 return call_tool_work(err);
388 return call_tool_work(TOOL_BUILD_DEPOT | GENERAL_TOOL, building->get_name(), 0, pl, pos);
391 call_tool_work build_bridge(player_t* pl, koord3d start, koord3d end,
const bridge_desc_t* bridge)
393 if (bridge == NULL) {
394 return call_tool_work(
"No bridge provided");
396 if (
const char* err = is_available(bridge)) {
397 return call_tool_work(err);
399 return call_tool_work(TOOL_BUILD_BRIDGE | GENERAL_TOOL, bridge->get_name(), 2, pl,
start, end);
402 call_tool_work build_bridge_at(player_t* pl, koord3d start,
const bridge_desc_t* bridge)
404 if (bridge == NULL) {
405 return call_tool_work(
"No bridge provided");
407 if (
const char* err = is_available(bridge)) {
408 return call_tool_work(err);
410 if (grund_t *gr =
world()->lookup(start)) {
413 if (
const char *err = bridge_builder_t::find_end_pos(pl, start, -koord(gr->get_weg_hang()), height, bridge, 1, 10,
false)) {
414 return call_tool_work(err);
416 return call_tool_work(TOOL_BUILD_BRIDGE | GENERAL_TOOL, bridge->get_name(), 0, pl,
start, end);
418 return call_tool_work(
"Bridge is too long for this type!\n");
421 call_tool_work set_slope(player_t* pl, koord3d start, my_slope_t
slope)
425 sprintf(buf,
"%2d", (uint8)slope);
426 static tool_setslope_t tool;
428 tool.old_slope_compatibility_mode =
false;
429 tool.set_default_param(buf);
430 return call_tool_work(&tool, pl, start);
433 call_tool_work restore_slope(player_t* pl, koord3d start)
435 return call_tool_work(TOOL_RESTORESLOPE | GENERAL_TOOL,
"", 0, pl, start);
438 const char* can_set_slope(player_t* pl, koord3d pos, my_slope_t slope)
440 return tool_setslope_t::tool_set_slope_work(pl, pos, slope,
false ,
true );
443 sint64 set_slope_get_price(my_slope_t slope)
445 return slope == RESTORE_SLOPE ? -welt->get_settings().cst_alter_land : -welt->get_settings().cst_set_slope;
448 call_tool_work build_sign_at(player_t* pl, koord3d start,
const roadsign_desc_t* sign)
451 return call_tool_work(
"No sign provided");
453 if (
const char* err = is_available(sign)) {
454 return call_tool_work(err);
456 return call_tool_work(TOOL_BUILD_ROADSIGN | GENERAL_TOOL, sign->get_name(), 0, pl,
start);
459 call_tool_work change_climate_at(player_t* pl, koord3d start,
int climate)
461 if (climate < water_climate || climate >= MAX_CLIMATES) {
462 return call_tool_work(
"Invalid climate number provided");
465 static cbuffer_t param;
467 param.printf(
"%d", climate);
468 return call_tool_work(TOOL_SET_CLIMATE | GENERAL_TOOL, param, 0, pl, start, start);
472 call_tool_work lower_raise(player_t* pl, koord3d pos,
bool lower)
475 switch(coordinate_transform_t::get_rotation()) {
476 case 1: pos += koord(1,0);
break;
477 case 2: pos += koord(1,1);
break;
478 case 3: pos += koord(0,1);
break;
481 return call_tool_work((lower ? TOOL_LOWER_LAND : TOOL_RAISE_LAND) | GENERAL_TOOL, NULL, 0, pl, pos);
484 void export_commands(HSQUIRRELVM vm)
492 create_class(vm,
"command_x");
499 register_function(vm, command_constructor,
"constructor", 2,
"xi");
501 sq_settypetag(vm, -1, param<tool_t*>::tag());
506 register_method(vm, &get_flags,
"get_flags",
true);
512 register_method(vm, &set_flags,
"set_flags",
true);
521 register_function(vm, command_work,
"work", -3,
"x t|x|y t|x|y");
536 register_function(vm,,
"work");
549 register_function(vm,,
"work");
559 STATIC register_method_fv(vm, build_way,
"build_way", freevariable<bool>(
false),
false,
true);
569 STATIC register_method(vm, build_way,
"build_road",
false,
true);
576 STATIC register_method(vm, build_depot,
"build_depot",
false,
true);
584 STATIC register_function(vm, command_build_station,
"build_station", -4 ,
585 func_signature_t<bsr_type>::get_typemask(
false).c_str(),
false );
587 log_squirrel_type(func_signature_t<bsr_type>::get_squirrel_class(
false),
"build_station", func_signature_t<bsr_type>::get_squirrel_type(
false, 0));
596 STATIC register_method(vm, build_bridge,
"build_bridge",
false,
true);
604 STATIC register_method(vm, build_bridge_at,
"build_bridge_at",
false,
true);
611 STATIC register_method(vm, set_slope,
"set_slope",
false,
true);
617 STATIC register_method(vm, restore_slope,
"restore_slope",
false,
true);
625 STATIC register_method(vm, can_set_slope,
"can_set_slope",
false,
true);
630 STATIC register_method(vm, set_slope_get_price,
"slope_get_price",
false,
true);
637 STATIC register_method(vm, build_sign_at,
"build_sign_at",
false,
true);
645 STATIC register_method(vm, build_wayobj,
"build_wayobj",
false,
true);
652 STATIC register_method(vm, change_climate_at,
"change_climate_at",
false,
true);
659 STATIC register_method_fv(vm, lower_raise,
"grid_lower", freevariable<bool>(
true),
false,
true);
665 STATIC register_method_fv(vm, lower_raise,
"grid_raise", freevariable<bool>(
false),
false,
true);