-- Freeciv - Copyright (C) 2007 - The Freeciv Project -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 2, or (at your option) -- any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- When creating new ruleset, you should copy this file only if you -- need to override default one. Usually you should implement your -- own scripts in ruleset specific script.lua. This way maintaining -- ruleset is easier as you do not need to keep your own copy of -- default.lua updated when ever it changes in Freeciv distribution. -- nef 2019/01/20 -- revision to allow for server to examine probability mass distribution -- also bug fix (was no consolation for no tech) -- changed "type" to "utype" _deflua_results = {} --[[ function table indexes (keys) are the tags also used to index mass profiles values are the (anonymous) functions associated with the mass]] -- Get gold from entering a hut. -- n.b. this is a service routine - not to be used in the results table function _deflua_hut_get_gold (unit, gold) local owner = unit.owner owner:change_gold(gold) notify.event(owner, unit.tile, E.HUT_GOLD, PL_("You found %d gold.", "You found %d gold.", gold), gold) return false end -- Default if intended hut behavior wasn`t possible. _deflua_hut_consolation_prize = function (unit) return _deflua_hut_get_gold(unit, 25) end _deflua_results.gold_25 = _deflua_hut_consolation_prize _deflua_results.gold_50 = function (unit) return _deflua_hut_get_gold(unit, 50) end _deflua_results.gold_100 = function (unit) return _deflua_hut_get_gold(unit, 100) end -- Get a tech from entering a hut. _deflua_results.technology = function (unit) local owner = unit.owner local tech = owner:give_tech(nil, -1, false, "hut") if tech then local tech_name = tech:name_translation() notify.event(owner, unit.tile, E.HUT_TECH, _("You found %s in ancient scrolls of wisdom."), tech_name) notify.research(owner, false, E.TECH_GAIN, -- /* TRANS: One player got tech for the whole team. */ _("The %s found %s in ancient scrolls of wisdom for you."), owner.nation:plural_translation(), tech_name) notify.research_embassies(owner, E.TECH_EMBASSY, -- /* TRANS: first %s is leader or team name */ _("%s has acquired %s from ancient scrolls of wisdom."), owner:research_name_translation(), tech_name) return false else return _deflua_hut_consolation_prize (unit) end end -- Get a mercenary unit from entering a hut. _deflua_results.mercenary = function (unit) local tile = unit.tile local owner = unit.owner local utype = find.role_unit_type('HutTech', owner) if not utype or not utype:can_exist_at_tile(tile) then utype = find.role_unit_type('Hut', nil) if not utype or not utype:can_exist_at_tile(tile) then return _deflua_hut_consolation_prize (unit) end end owner:create_unit(tile, utype, 0, unit:get_homecity(), -1) notify.event(owner, tile, E.HUT_MERC, _("A band of friendly mercenaries joins your cause.")) return false end -- Get barbarians from hut, unless close to a city, king enters, or -- barbarians are disabled -- Unit may die: returns true if unit is dead _deflua_results.barbarians = function (unit) local tile = unit.tile local utype = unit.utype local owner = unit.owner if server.setting.get("barbarians") == "DISABLED" or tile:city_exists_within_max_city_map(true) or utype:has_flag('Gameloss') then notify.event(owner, tile, E.HUT_BARB_CITY_NEAR, _("An abandoned village is here.")) return false elseif tile:unleash_barbarians() then notify.event(owner, tile, E.HUT_BARB, _("You have unleashed a horde of barbarians!")) return false else notify.event(owner, tile, E.HUT_BARB_KILLED, _("Your %s has been killed by barbarians!"), utype:name_translation()); return true end end -- Get new city from hut, or settlers (nomads) if terrain is poor. _deflua_hut_get_settlers = function (unit) local tile = unit.tile local owner = unit.owner local settlers = find.role_unit_type('Cities', owner) if settlers and settlers:can_exist_at_tile(tile) then owner:create_unit(tile, settlers, 0, unit:get_homecity(), -1) notify.event(owner, tile, E.HUT_SETTLER, _("Friendly nomads are impressed by you, and join you.") ) return false else return _deflua_hut_consolation_prize (unit) end end --[[ _deflua_hut_get_settlers could also be made another _deflua_results.* function offering another profile option initially with mass = 0 e.g. _deflua_results.settlers = _deflua_hut_get_settlers hut.default.settlers = 0 -- move down to where the others are]] _deflua_results.city = function (unit) if unit:is_on_possible_city_tile() then local owner = unit.owner local tile = unit.tile owner:create_city(tile, "") notify.event(owner, tile, E.HUT_CITY, _("You found a friendly city.") ) return false else return _deflua_hut_get_settlers(unit) end end hut ={} --[[this needs to be shared with the server as global data; c routines would then need to examine the Lua data, or alternatively, if/when the profiles are defined in the ruleset the server should export the data into Lua format prior to this script being run (i.e. during "/start"). When multiple hut types become available 'hut' will become a field in table of hut types]] --[[ The tags indexing hut[profile] must be the same as those used to index the table "_deflua_results" (see functions above). Entries with 0 mass can be added (or deleted) as you please and could be used for placeholders etc. (for the server).]] --[[ not clear to me how case is handled in the c - Lua interface - it may be that all tags should be all uppercase including default, handicap etc. - or initial cap? i.e. where should string.upper(), ~lower() be used?]] -- all mass numbers in profiles (e.g. hut.default) should be >= 0 hut.default = {gold_25 = 1, gold_50 = 3, gold_100 = 1, technology = 3, mercenary = 2, barbarians = 1, city = 1, } -- hut.handicap = {gold_25 = 1, gold_50 = 0, gold_100 = 0, technology = 0, -- mercenary = 0, barbarians = 1, city = 0, -- } --[[The body of the iterates in _deflua_hut_enter_callback could be restructured to have a test 'if type (_deflua_results [key]) == "function" ' at the beginning of EACH, or just in the nested 'if' of the second. Depends on how the server deals with the profiles. A test for mass < 0 may also be prudent. Current code is reliant on profile table being a correct match to the results table, i.e. no unmatched profile entries with mass > 0, and no mass < 0 ]] -- Randomly choose a hut event function _deflua_hut_enter_callback(unit) notify.event( nil, nil, E.CHAT_MSG, "Lua default 20190202.0") local profile = hut.default -- change to deal with profile selection -- allow for the mass distribution to be completely dynamic local total = 0 for key, mass in pairs (profile) do total = total + mass end -- if total < 1 -- then return false -- should never get here -- end total = random(1, total) for key, mass in pairs (profile) do total = total - mass if total <= 0 then return _deflua_results [key] (unit) end end return false -- SHOULD NEVER GET HERE end --[[ Maybe replace "should never get here" defaults with an "empty village" message perhaps worded with a hint of "something has gone wrong". Also some kind of assertion failure to create a log entry?]] signal.connect("hut_enter", "_deflua_hut_enter_callback") --[[ Make partisans around conquered city if requirements to make partisans when a city is conquered is fulfilled this routine makes a lot of partisans based on the city`s size. To be candidate for partisans the following things must be satisfied: 1) The loser of the city is the original owner. 2) The Inspire_Partisans effect must be larger than zero. If these conditions are ever satisfied, the ruleset must have a unit with the Partisan role. In the default ruleset, the requirements for inspiring partisans are: a) Guerilla warfare must be known by atleast 1 player b) The player must know about Communism and Gunpowder c) The player must run either a democracy or a communist society. ]]-- function _deflua_make_partisans_callback(city, loser, winner, reason) if reason ~= 'conquest' or city:inspire_partisans(loser) <= 0 then return end local partisans = random(0, 1 + (city.size + 1) / 2) + 1 if partisans > 8 then partisans = 8 end city.tile:place_partisans(loser, partisans, city:map_sq_radius()) notify.event(loser, city.tile, E.CITY_LOST, _("The loss of %s has inspired partisans!"), city.name) notify.event(winner, city.tile, E.UNIT_WIN_ATT, _("The loss of %s has inspired partisans!"), city.name) end signal.connect("city_transferred", "_deflua_make_partisans_callback") -- Notify player about the fact that disaster had no effect if that is -- the case function _deflua_harmless_disaster_message(disaster, city, had_internal_effect) if not had_internal_effect then notify.event(city.owner, city.tile, E.DISASTER, _("We survived the disaster without serious damage.")) end end signal.connect("disaster_occurred", "_deflua_harmless_disaster_message")