From 68935cee04d509ccab57936c2a6c3bc25863c8ee Mon Sep 17 00:00:00 2001 From: Sveinung Kvilhaugsvik Date: Thu, 11 Mar 2021 00:44:06 +0100 Subject: [PATCH 2/2] Lua API: allow setting move side effects. The Lua API allows moving a unit without considering what the move rules are via edit.unit_move() and edit.unit_teleport(). This can be used to create custom move actions, teleporting items on the map etc. They have side effects that used to be a part of regular moves but that now live in separate actions. Add parameters to control what side effects not a part of enabler controlled moves the move should have. This allows the ability to specify a unit to embark to, to determine if a unit is allowed to unload from its current transport to perform the move, if any city at the target tile is conquered, if any extra at the target tile is conquered, if huts at the target tile are entered or frightened. The old versions of edit.unit_move() and edit.unit_teleport() that infers side effects based on game rules and state can be deprecated as soon as enough of their old rules can be expressed in Lua. See osdn #41730 --- server/scripting/api_server_edit.c | 74 +++++++++++++++++++++++++++++- server/scripting/api_server_edit.h | 13 +++++- server/scripting/tolua_server.pkg | 42 ++++++++++++++--- 3 files changed, 119 insertions(+), 10 deletions(-) diff --git a/server/scripting/api_server_edit.c b/server/scripting/api_server_edit.c index 93fb8273ee..0da5de694b 100644 --- a/server/scripting/api_server_edit.c +++ b/server/scripting/api_server_edit.c @@ -156,7 +156,52 @@ Unit *api_edit_create_unit_full(lua_State *L, Player *pplayer, Tile *ptile, /*************************************************************************//** Teleport unit to destination tile *****************************************************************************/ -bool api_edit_unit_teleport(lua_State *L, Unit *punit, Tile *dest) +bool api_edit_unit_teleport(lua_State *L, Unit *punit, Tile *dest, + Unit *embark_to, bool allow_disembark, + bool conquer_city, bool conquer_extra, + bool enter_hut, bool frighten_hut) +{ + bool alive; + struct city *pcity; + + LUASCRIPT_CHECK_STATE(L, FALSE); + LUASCRIPT_CHECK_ARG_NIL(L, punit, 2, Unit, FALSE); + LUASCRIPT_CHECK_ARG_NIL(L, dest, 3, Tile, FALSE); + + if (!allow_disembark && unit_transported(punit)) { + /* Can't leave the transport. */ + return TRUE; + } + + pcity = tile_city(dest); + + /* Teleport first so destination is revealed even if unit dies */ + alive = unit_move(punit, dest, 0, + embark_to, embark_to != NULL, + conquer_city, conquer_extra, + enter_hut, frighten_hut); + if (alive) { + struct player *owner = unit_owner(punit); + + if (!can_unit_exist_at_tile(&(wld.map), punit, dest) + && !unit_transported(punit)) { + wipe_unit(punit, ULR_NONNATIVE_TERR, NULL); + return FALSE; + } + if (is_non_allied_unit_tile(dest, owner) + || (pcity && !pplayers_allied(city_owner(pcity), owner))) { + wipe_unit(punit, ULR_STACK_CONFLICT, NULL); + return FALSE; + } + } + + return alive; +} + +/*************************************************************************//** + Teleport unit to destination tile +*****************************************************************************/ +bool api_edit_unit_teleport_old(lua_State *L, Unit *punit, Tile *dest) { bool alive; struct city *pcity; @@ -819,7 +864,32 @@ void api_edit_player_victory(lua_State *L, Player *pplayer) Move a unit. *****************************************************************************/ bool api_edit_unit_move(lua_State *L, Unit *punit, Tile *ptile, - int movecost) + int movecost, + Unit *embark_to, bool disembark, + bool conquer_city, bool conquer_extra, + bool enter_hut, bool frighten_hut) +{ + LUASCRIPT_CHECK_STATE(L, FALSE); + LUASCRIPT_CHECK_SELF(L, punit, FALSE); + LUASCRIPT_CHECK_ARG_NIL(L, ptile, 3, Tile, FALSE); + LUASCRIPT_CHECK_ARG(L, movecost >= 0, 4, "Negative move cost!", FALSE); + + if (!disembark && unit_transported(punit)) { + /* Can't leave the transport. */ + return TRUE; + } + + return unit_move(punit, ptile, movecost, + embark_to, embark_to != NULL, + conquer_city, conquer_extra, + enter_hut, frighten_hut); +} + +/*************************************************************************//** + Move a unit. +*****************************************************************************/ +bool api_edit_unit_move_old(lua_State *L, Unit *punit, Tile *ptile, + int movecost) { struct city *pcity; diff --git a/server/scripting/api_server_edit.h b/server/scripting/api_server_edit.h index c25fc93eba..3f85e61ad1 100644 --- a/server/scripting/api_server_edit.h +++ b/server/scripting/api_server_edit.h @@ -35,7 +35,11 @@ Unit *api_edit_create_unit_full(lua_State *L, Player *pplayer, Tile *ptile, Unit_Type *ptype, int veteran_level, City *homecity, int moves_left, int hp_left, Unit *ptransport); -bool api_edit_unit_teleport(lua_State *L, Unit *punit, Tile *dest); +bool api_edit_unit_teleport(lua_State *L, Unit *punit, Tile *dest, + Unit *embark_to, bool allow_disembark, + bool conquer_city, bool conquer_extra, + bool enter_hut, bool frighten_hut); +bool api_edit_unit_teleport_old(lua_State *L, Unit *punit, Tile *dest); bool api_edit_perform_action_unit_vs_city(lua_State *L, Unit *punit, Action *paction, City *tgt); @@ -90,7 +94,12 @@ Player *api_edit_civil_war(lua_State *L, Player *pplayer, int probability); void api_edit_player_victory(lua_State *L, Player *pplayer); bool api_edit_unit_move(lua_State *L, Unit *punit, Tile *ptile, - int movecost); + int movecost, + Unit *embark_to, bool allow_disembark, + bool conquer_city, bool conquer_extra, + bool enter_hut, bool frighten_hut); +bool api_edit_unit_move_old(lua_State *L, Unit *punit, Tile *ptile, + int movecost); void api_edit_unit_moving_disallow(lua_State *L, Unit *punit); void api_edit_unit_moving_allow(lua_State *L, Unit *punit); diff --git a/server/scripting/tolua_server.pkg b/server/scripting/tolua_server.pkg index e5f4264828..965af66055 100644 --- a/server/scripting/tolua_server.pkg +++ b/server/scripting/tolua_server.pkg @@ -116,8 +116,13 @@ module edit { @ create_unit_full (lua_State *L, Player *pplayer, Tile *ptile, Unit_Type *ptype, int veteran_level, City *homecity, int moves_left, int hp_left, Unit *ptransport); - bool api_edit_unit_teleport + bool api_edit_unit_teleport_old @ unit_teleport(lua_State *L, Unit *self, Tile *dest); + bool api_edit_unit_teleport + @ unit_teleport(lua_State *L, Unit *self, Tile *dest, + Unit *embark_to, bool allow_disembark, + bool conquer_city, bool conquer_extra, + bool enter_hut, bool frighten_hut); void api_edit_unit_kill @ unit_kill(lua_State *L, Unit *self, const char *reason, Player *killer); @@ -176,8 +181,13 @@ module edit { @ unit_turn(lua_State *L, Unit *punit, Direction dir); void api_edit_player_victory @ player_victory (lua_State *L, Player *self); - bool api_edit_unit_move + bool api_edit_unit_move_old @ unit_move(lua_State *L, Unit *self, Tile *moveto, int movecost); + bool api_edit_unit_move + @ unit_move(lua_State *L, Unit *self, Tile *moveto, int movecost, + Unit *embark_to, bool allow_disembark, + bool conquer_city, bool conquer_extra, + bool enter_hut, bool frighten_hut); void api_edit_unit_moving_disallow @ movement_disallow(lua_State *L, Unit *self); void api_edit_unit_moving_allow @@ -351,8 +361,18 @@ function City:add_history(amount) end -- Server functions for Unit module -function Unit:teleport(dest) - return edit.unit_teleport(self, dest) +function Unit:teleport(dest, + embark_to, allow_disembark, + conquer_city, conquer_extra, + enter_hut, frighten_hut) + if allow_disembark == nil then + return edit.unit_teleport(self, dest) + else + return edit.unit_teleport(self, dest, + embark_to, allow_disembark, + conquer_city, conquer_extra, + enter_hut, frighten_hut) + end end function Unit:perform_action(action, target, sub_target) @@ -373,8 +393,18 @@ function Unit:kill(reason, killer) edit.unit_kill(self, reason, killer) end -function Unit:move(moveto, movecost) - return edit.unit_move(self, moveto, movecost) +function Unit:move(moveto, movecost, + embark_to, allow_disembark, + conquer_city, conquer_extra, + enter_hut, frighten_hut) + if allow_disembark == nil then + return edit.unit_move(self, moveto, movecost) + else + return edit.unit_move(self, moveto, movecost, + embark_to, allow_disembark, + conquer_city, conquer_extra, + enter_hut, frighten_hut) + end end function Unit:movement_disallow() -- 2.20.1