diff --git a/server/plrhand.c b/server/plrhand.c index ba2ee5bda0..47d97a0a5b 100644 --- a/server/plrhand.c +++ b/server/plrhand.c @@ -399,6 +399,86 @@ void government_change(struct player *pplayer, struct government *gov, send_research_info(presearch, NULL); } +/**********************************************************************//** + pvictor gets parts of treasury, map and cities of pvictim. + Normally happens when pvictim's gameloss unit is killed. + FIXME: any control over types of the loot? +**************************************************************************/ +void player_loot_player(struct player *pvictor, struct player *pvictim) +{ + int ransom = fc_rand(1 + pvictim->economic.gold); + int n = 1 + fc_rand(3); + + /* give map */ + give_distorted_map(pvictim, pvictor, 50, TRUE); + + log_debug("victim has money: %d", pvictim->economic.gold); + pvictor->economic.gold += ransom; + pvictim->economic.gold -= ransom; + + while (n > 0) { + Tech_type_id ttid = steal_a_tech(pvictor, pvictim, A_UNSET); + + if (ttid == A_NONE) { + log_debug("Worthless enemy doesn't have more techs to steal."); + break; + } else { + log_debug("Pressed tech %s from captured enemy", + research_advance_rule_name(research_get(pvictor), ttid)); + if (!fc_rand(3)) { + break; /* out of luck */ + } + n--; + } + } + + { /* try to submit some cities */ + int vcsize = city_list_size(pvictim->cities); + int evcsize = vcsize; + int conqsize = evcsize; + + if (evcsize < 3) { + evcsize = 0; + } else { + evcsize -=3; + } + /* about a quarter on average with high numbers less probable */ + conqsize = fc_rand(fc_rand(evcsize)); + + log_debug("conqsize=%d", conqsize); + + if (conqsize > 0) { + bool palace = game.server.savepalace; + bool submit = FALSE; + + game.server.savepalace = FALSE; /* moving it around is dumb */ + + city_list_iterate_safe(pvictim->cities, pcity) { + /* kindly ask the citizens to submit */ + if (fc_rand(vcsize) < conqsize) { + submit = TRUE; + } + vcsize--; + if (submit) { + conqsize--; + /* Transfer city to the victorious player + * kill all its units outside of a radius of 7, + * give verbose messages of every unit transferred, + * and raze buildings according to raze chance + * (also removes palace) */ + (void) transfer_city(pvictor, pcity, 7, TRUE, TRUE, TRUE, + !is_barbarian(pvictor)); + submit = FALSE; + } + if (conqsize <= 0) { + break; + } + } city_list_iterate_safe_end; + game.server.savepalace = palace; + } + } +} + /**********************************************************************//** Get length of a revolution. **************************************************************************/ diff --git a/server/plrhand.h b/server/plrhand.h index 83e0311ed0..beef551e10 100644 --- a/server/plrhand.h +++ b/server/plrhand.h @@ -40,6 +40,7 @@ void kill_player(struct player *pplayer); void update_revolution(struct player *pplayer); void government_change(struct player *pplayer, struct government *gov, bool revolution_finished); +void player_loot_player(struct player *pvictor, struct player *pvictim); int revolution_length(struct government *gov, struct player *plr); void update_capital(struct player *pplayer); diff --git a/server/scripting/api_server_game_methods.c b/server/scripting/api_server_game_methods.c index ff2a0a6726..bd8cf56a7f 100644 --- a/server/scripting/api_server_game_methods.c +++ b/server/scripting/api_server_game_methods.c @@ -21,6 +21,9 @@ /* ai */ #include "aitraits.h" /* ai_trait_get_value() */ +/* server */ +#include "plrhand.h" + /* server/scripting */ #include "script_server.h" @@ -84,6 +87,26 @@ int api_methods_player_trait_current_mod(lua_State *L, Player *pplayer, return pplayer->ai_common.traits[tr].mod; } +/**********************************************************************//** + Mark the player as one who lost the game, optionally giving some loot + to looter. This method only marks the nation for wipeout, it happens + only when kill_dying_players() is called from C code. +**************************************************************************/ +void api_methods_player_lose(lua_State *L, Player *pplayer, Player *looter) +{ + LUASCRIPT_CHECK_STATE(L); + LUASCRIPT_CHECK_SELF(L, pplayer); + + if (!pplayer->is_alive) { + luascript_arg_error(L, 1, "the player has already lost"); + return; /* we won't rob the graves */ + } + if (looter) { + player_loot_player(looter, pplayer); + } + player_status_add(pplayer, PSTATUS_DYING); +} + /**********************************************************************//** Return the minimum random trait value that will be allocated for a nation **************************************************************************/ diff --git a/server/scripting/api_server_game_methods.h b/server/scripting/api_server_game_methods.h index 369a336a41..404ec1bc69 100644 --- a/server/scripting/api_server_game_methods.h +++ b/server/scripting/api_server_game_methods.h @@ -29,6 +29,7 @@ int api_methods_player_trait_base(lua_State *L, Player *pplayer, const char *tname); int api_methods_player_trait_current_mod(lua_State *L, Player *pplayer, const char *tname); +void api_methods_player_lose(lua_State *L, Player *pplayer, Player *looter); int api_methods_nation_trait_min(lua_State *L, Nation_Type *pnation, const char *tname); diff --git a/server/scripting/tolua_server.pkg b/server/scripting/tolua_server.pkg index 40353ba40a..4370d44de7 100644 --- a/server/scripting/tolua_server.pkg +++ b/server/scripting/tolua_server.pkg @@ -499,8 +499,14 @@ module Player { @ trait_base (lua_State *L, Player *pplayer, const char *tname); int api_methods_player_trait_current_mod @ trait_current_mod (lua_State *L, Player *pplayer, const char *tname); + void api_methods_player_lose + @ lose (lua_State *L, Player *pplayer, Player *looter = NULL); } +$[ + edit.player_lose = Player.lose +$] + /* server game parameters */ $#define game_server_autoupgrade_veteran_loss (game.server.autoupgrade_veteran_loss) $#define game_server_upgrade_veteran_loss (game.server.upgrade_veteran_loss) diff --git a/server/unittools.c b/server/unittools.c index c5d60d9f54..0b7c2c3c8e 100644 --- a/server/unittools.c +++ b/server/unittools.c @@ -2160,79 +2160,7 @@ void kill_unit(struct unit *pkiller, struct unit *punit, bool vet) if ((game.info.gameloss_style & GAMELOSS_STYLE_LOOT) && unit_has_type_flag(punit, UTYF_GAMELOSS)) { - ransom = fc_rand(1 + pvictim->economic.gold); - int n; - - /* give map */ - give_distorted_map(pvictim, pvictor, 50, TRUE); - - log_debug("victim has money: %d", pvictim->economic.gold); - pvictor->economic.gold += ransom; - pvictim->economic.gold -= ransom; - - n = 1 + fc_rand(3); - - while (n > 0) { - Tech_type_id ttid = steal_a_tech(pvictor, pvictim, A_UNSET); - - if (ttid == A_NONE) { - log_debug("Worthless enemy doesn't have more techs to steal."); - break; - } else { - log_debug("Pressed tech %s from captured enemy", - research_advance_rule_name(research_get(pvictor), ttid)); - if (!fc_rand(3)) { - break; /* out of luck */ - } - n--; - } - } - - { /* try to submit some cities */ - int vcsize = city_list_size(pvictim->cities); - int evcsize = vcsize; - int conqsize = evcsize; - - if (evcsize < 3) { - evcsize = 0; - } else { - evcsize -=3; - } - /* about a quarter on average with high numbers less probable */ - conqsize = fc_rand(fc_rand(evcsize)); - - log_debug("conqsize=%d", conqsize); - - if (conqsize > 0) { - bool palace = game.server.savepalace; - bool submit = FALSE; - - game.server.savepalace = FALSE; /* moving it around is dumb */ - - city_list_iterate_safe(pvictim->cities, pcity) { - /* kindly ask the citizens to submit */ - if (fc_rand(vcsize) < conqsize) { - submit = TRUE; - } - vcsize--; - if (submit) { - conqsize--; - /* Transfer city to the victorious player - * kill all its units outside of a radius of 7, - * give verbose messages of every unit transferred, - * and raze buildings according to raze chance - * (also removes palace) */ - (void) transfer_city(pvictor, pcity, 7, TRUE, TRUE, TRUE, - !is_barbarian(pvictor)); - submit = FALSE; - } - if (conqsize <= 0) { - break; - } - } city_list_iterate_safe_end; - game.server.savepalace = palace; - } - } + player_loot_player(pvictor, pvictim); } /* barbarian leader ransom hack */