Project

General

Profile

Feature #1464 » specialists-lua-api.patch

Alexandr Ignatiev, 05/31/2025 12:47 AM

View differences:

common/scriptcore/api_game_effects.c
etype);
}
/***********************************************************************//**
Get effect bonus for specialist.
@param L Lua State to use
@param s Specialist to get the effect value for
@param d Optional: City or Player for which the effect
is calculated (if City, its owner becomes the player)
@param output_id Optional: Indetifier of the output related
to the effect (e.g. Output to harvest from s)
@param effect_type Effect to check
@return Effect bonus value
***************************************************************************/
int
api_effects_specialist_bonus(lua_State *L, Specialist *s, lua_Object d,
const char *output_id, const char *effect_type)
{
struct req_context ctx = {.specialist = s};
enum effect_type etype;
LUASCRIPT_CHECK_STATE(L, 0);
LUASCRIPT_CHECK_ARG_NIL(L, s, 2, Specialist, 0);
LUASCRIPT_CHECK_ARG_NIL(L, effect_type, 5, string, 0);
etype = effect_type_by_name(effect_type, fc_strcasecmp);
if (!effect_type_is_valid(etype)) {
return 0;
}
if (output_id != NULL) {
enum output_type_id id = output_type_by_identifier(output_id);
if (O_LAST == id){
char msg[255];
fc_snprintf(msg, sizeof(msg),
"Unknown output identifier \"%s\"", output_id);
LUASCRIPT_CHECK_ARG(L, id != O_LAST, 3, msg, 0); /* Fails */
}
ctx.output = get_output_type(id);
}
if (0 != d) {
tolua_Error e; /* ignored */
if (tolua_isusertype(L, d, "Player", 0, &e)) {
/* nil handled here */
ctx.player = (Player *) lua_touserdata(L, d);
} else if (tolua_isusertype(L, d, "City", 0, &e)) {
ctx.city = (City *) lua_touserdata(L, d);
if (ctx.city) {
ctx.player = city_owner(ctx.city);
}
} else {
char msg[255];
fc_snprintf(msg, sizeof(msg),
"got '%s', City or Player expected", tolua_typename(L, d));
LUASCRIPT_CHECK_ARG(L, FALSE, 2, msg, 0); /* Fails */
}
}
return get_target_bonus_effects(nullptr, &ctx, nullptr, etype);
}
/***********************************************************************//**
Returns the effect bonus at a tile and the specified unit.
Unlike effects.unit_bonus() the city the effect is evaluated against is
common/scriptcore/api_game_effects.h
const char *effect_type);
int api_effects_tile_bonus(lua_State *L, Tile *ptile, City *pcity,
const char *output_id, const char *effect_type);
int
api_effects_specialist_bonus(lua_State *L, Specialist *s, lua_Object d,
const char *output_id, const char *effect_type);
int api_effects_unit_vs_tile_bonus(lua_State *L, Unit *punit, Tile *ptile,
const char *effect_type);
common/scriptcore/api_game_methods.c
return citizens_nation_get(pcity, nationality->slot);
}
/**********************************************************************//**
Return number of specialists of type s working in pcity.
If no s is specified, return number of citizens employed as specialists.
**************************************************************************/
int api_methods_city_num_specialists(lua_State *L, City *pcity,
Specialist *s)
{
LUASCRIPT_CHECK_STATE(L, 0);
LUASCRIPT_CHECK_SELF(L, pcity, 0);
if (nullptr != s) {
return pcity->specialists[specialist_index(s)];
} else {
return city_specialists(pcity);
}
}
/**********************************************************************//**
Return if pcity agrees with reqs of specialist s
**************************************************************************/
bool api_methods_city_can_employ(lua_State *L, City *pcity, Specialist *s)
{
LUASCRIPT_CHECK_STATE(L, FALSE);
LUASCRIPT_CHECK_SELF(L, pcity, FALSE);
LUASCRIPT_CHECK_ARG_NIL(L, s, 3, Specialist, FALSE);
return city_can_use_specialist(pcity, specialist_index(s));
}
/**********************************************************************//**
Return rule name for Government
**************************************************************************/
......
return can_player_build_improvement_direct(pplayer, itype);
}
/**********************************************************************//**
Return if pplayer agrees with Player+-ranged reqs of specialist s
**************************************************************************/
bool api_methods_player_can_employ(lua_State *L, Player *pplayer,
Specialist *s)
{
LUASCRIPT_CHECK_STATE(L, FALSE);
LUASCRIPT_CHECK_SELF(L, pplayer, FALSE);
LUASCRIPT_CHECK_ARG_NIL(L, s, 3, Specialist, FALSE);
return
are_reqs_active_ranges(REQ_RANGE_PLAYER, REQ_RANGE_WORLD,
&(const struct req_context) {
.player = pplayer,
}, nullptr, &s->reqs, RPT_POSSIBLE);
}
/**********************************************************************//**
Find player's primary capital, if known
**************************************************************************/
common/scriptcore/api_game_methods.h
bool api_methods_is_primary_capital(lua_State *L, City *pcity);
int api_methods_city_nationality_citizens(lua_State *L, City *pcity,
Player *nationality);
int api_methods_city_num_specialists(lua_State *L, City *pcity,
Specialist *s);
bool api_methods_city_can_employ(lua_State *L, City *pcity, Specialist *s);
/* Counter */
const char *api_methods_counter_rule_name(lua_State *L, Counter *c);
......
Unit_Type *utype);
bool api_methods_player_can_build_impr_direct(lua_State *L, Player *pplayer,
Building_Type *itype);
bool api_methods_player_can_employ(lua_State *L, Player *pplayer,
Specialist *s);
City *api_methods_player_primary_capital(lua_State *L, Player *pplayer);
common/scriptcore/tolua_game.pkg
@ can_build_direct(lua_State *L, Player *pplayer, Building_Type *itype);
bool api_methods_player_can_build_unit_direct
@ can_build_direct(lua_State *L, Player *pplayer, Unit_Type *utype);
bool api_methods_player_can_employ
@ can_employ(lua_State *L, Player *pplayer, Specialist *s);
City *api_methods_player_primary_capital
@ primary_capital(lua_State *L, Player *pplayer);
......
int api_methods_city_nationality_citizens
@ nationality_citizens(lua_State *L, City *self, Player *nationality);
bool api_methods_city_can_employ
@ can_employ(lua_State *L, City *pcity, Specialist *s);
int api_methods_city_num_specialists
@ num_specialists (lua_State *L, City *pcity, Specialist *s);
}
$[
......
int api_effects_tile_bonus
@ tile_bonus(lua_State *L, Tile *ptile, City *pcity,
const char *output_id, const char *effect_type);
int api_effects_specialist_bonus
@ specialist_bonus (lua_State *L, Specialist *s, lua_Object d,
const char *output_id, const char *effect_type);
int api_effects_unit_vs_tile_bonus
@ unit_vs_tile_bonus(lua_State *L, Unit *punit, Tile *ptile,
const char *effect_type);
server/scripting/api_server_edit.c
}
}
/**********************************************************************//**
Reduce specialists of given type s in a way like toggling in the client.
Does not place workers on map, just switches to another specialist.
Does nothing if there is less than amount specialists s in pcity.
Return if given number could be repurposed.
**************************************************************************/
bool api_edit_city_reduce_specialists(lua_State *L, City *pcity,
Specialist *s, int amount)
{
Specialist_type_id from, to;
LUASCRIPT_CHECK_STATE(L, FALSE);
LUASCRIPT_CHECK_SELF(L, pcity, FALSE);
LUASCRIPT_CHECK_ARG_NIL(L, s, 2, Specialist, FALSE);
LUASCRIPT_CHECK_ARG(L, amount >= 0, 3, "must be non-negative", FALSE);
from = specialist_index(s);
if (pcity->specialists[from] < amount) {
return FALSE;
}
to = from;
do {
to = (to + 1) % specialist_count();
} while (to != from && !city_can_use_specialist(pcity, to));
if (to == from) {
/* We can use only the default specialist */
return FALSE;
} else {
/* City population must be correct */
fc_assert_ret_val_msg((int) pcity->specialists[to] + amount <= MAX_CITY_SIZE,
FALSE, "Wrong specialist number in %s",
city_name_get(pcity));
pcity->specialists[from] -= amount;
pcity->specialists[to] += amount;
city_refresh(pcity);
/* sanity_check_city(pcity); -- hopefully we don't break things here? */
send_city_info(city_owner(pcity), pcity);
/* FIXME: notify global observers? */
return TRUE;
}
}
/**********************************************************************//**
Create a new player.
**************************************************************************/
server/scripting/api_server_edit.h
bool api_edit_transfer_city(lua_State *L, City *pcity, Player *new_owner);
void api_edit_create_building(lua_State *L, City *pcity, Building_Type *impr);
void api_edit_remove_building(lua_State *L, City *pcity, Building_Type *impr);
bool api_edit_city_reduce_specialists(lua_State *L, City *pcity,
Specialist *s, int amount);
Player *api_edit_create_player(lua_State *L, const char *username,
Nation_Type *pnation, const char *ai);
void api_edit_change_gold(lua_State *L, Player *pplayer, int amount);
server/scripting/tolua_server.pkg
@ create_building (lua_State *L, City *pcity, Building_Type *impr);
void api_edit_remove_building
@ remove_building (lua_State *L, City *pcity, Building_Type *impr);
bool api_edit_city_reduce_specialists
@ reduce_specialists (lua_State *L, City *pcity, Specialist *s,
int amount = 1);
void api_edit_create_owned_extra
@ create_owned_extra (lua_State *L, Tile *ptile,
const char *name, Player *pplayer);
......
edit.remove_building(self, impr)
end
City.reduce_specialists = edit.reduce_specialists;
function City:change_size(change, nationality)
edit.change_city_size(self, change, nationality)
end
(1-1/3)