Quantcast Events Tutorial - Freeciv.org
Recent changes Random page
GAMING
Gaming
 
WoWWiki
Halopedia
FFXIclopedia
Age of Conan
Warhammer Online
Grand Theft Wiki
See more...

Events Tutorial

From Freeciv

Jump to: navigation, search

So you want to add some events, but you have no idea how? Well you've come to the right place, because so do I. This tutorial documents my journey into the world of events (it may later be refined to be a more straightforward tutorial).

Updated as of 2.1 development version post-beta4.

Contents

[edit] The basic premise

An event includes a trigger (signal) and an action. In the script code you will write, you create a callback function using the Lua scripting language. This callback function provides the actions and is linked up to a trigger that is invoked from the freeciv code itself.

An example is

signal.connect('unit_moved', 'unit_moved_callback')

which registers the script to listen for unit_moved events. unit_moved_callback should be a function in the Lua script.

[edit] Getting started

You may add events either to a ruleset or to a scenario. Changing the ruleset will affect anyone who plays with that ruleset; if you add an event to the default ruleset it will affect almost everyone. Adding an event to the scenario means only someone who plays with your scenario will get this event. As an example, the civ2 ruleset is a ruleset, while a Europe or World-War-Two scenario would probably be scenarios.

To add events to the ruleset you must edit the events.lua file in the ruleset directory. This is pretty straightforward.

To add events to the scenario you must add some script code directly inside the .sav file itself. This means you add a section

[script]
code=$
...
$

to the .sav file. The code you will write goes in place of the ... bits between the $ signs.

To see how this works in practice, look in the tutorial at data/scenario/tutorial.sav.gz ; the file can be uncompressed and viewed in a text editor.

[edit] An Example

An example that could be used in the tutorial: Tell the user that the found spot is good for a city

[script]
code=$
-- This line is a comment since it is marked with two dashes
function has_unit_type_name(unit, utype_name) 
  return (unit.utype.id == find.unit_type(utype_name).id)
end
function has_terrain_name(tile, terrain_name)
  return (tile.terrain.id == find.terrain(terrain_name).id)
end

-- Here we handle moved unit events
function unit_moved_callback(unit, src_tile, dst_tile)
  if unit.owner:is_human() then
    if has_unit_type_name(unit, 'Settlers')
      and ( has_terrain_name(dst_tile, 'Grassland') 
      or has_terrain_name(dst_tile, 'Plains') ) then  
      notify.event(unit.owner, dst_tile, E.TUTORIAL,
_("This looks like a good place to build a city.  The next time this\n\
unit gets a chance to move, press (b) to found a city.\n\
\n\
In general you want to build cities on open ground near water.  Food\n\
is the most important resource for any city.  Grassland and plains\n\
provide plenty of food."))
    end
  end
end
signal.connect('unit_moved', 'unit_moved_callback')
$

[edit] Scripting API

[edit] Signals

/**************************************************************************
  Signals implementation.
  
  ...
  
  A signal may have any number of Lua callback functions connected to it
  at any given time.

  A signal emission invokes all associated callbacks in the order they were
  connected:

  * A callback can stop the current signal emission, preventing the callbacks
    connected after it from being invoked.

  * A callback can detach itself from its associated signal.
  
  Lua callbacks functions are able to do these via their return values.
  
  All Lua callback functions can return a value. Example:
    return false
    
  If the value is 'true' the current signal emission will be stopped.
**************************************************************************/

Defined signal names and their callback signatures

turn_started    (turn, year)
unit_moved    (unit, src_tile, dst_tile)
city_built    (city)
city_growth    (city, size)

/* Only includes units built in cities, for now.  */
unit_built    (unit, city)
building_built    (building_type, city)

  /* These can happen for various reasons; the third argument gives the
   * reason (a simple string identifier).  Example identifiers:
   * "pop_cost", "need_tech", "need_building", "need_special",
   * "need_terrain", "need_government", "need_nation", "never",
   * "unavailable". */
unit_cant_be_built    (unit_type, city, string)
building_cant_be_built    (building_type, city, string)

  /* The third argument contains the source: "researched", "traded",
   * "stolen", "hut". */
tech_researched    (tech_type, player, string)
hut_enter    (unit)


[edit] Data Types

The Scripting API has a number of fundamental Data types:

Player
  string      name
  Nation_Type nation
  Player_ai   ai
  int         id

City
  string      name
  Player      owner
  Tile        tile
  int         id
  
Unit
  Unit_Type   utype
  Player      owner
  int         homecity_id
  Tile        tile
  int         id

Tile
  int         nat_x
  int         nat_y
  Terrain     terrain
  int         id

Government
  int         id

Nation_Type
  int         id

Building_Type
  int         build_cost
  int         id

Unit_Type
  int         build_cost
  int         id

[edit] Methods and functions

-- Player methods.
Player:is_human()
Player:num_cities()
Player:num_units()

-- Unit methods.
Unit:homecity()

-- Building_Type methods.
Building_Type:build_shield_cost()
Building_Type:is_wonder()
Building_Type:is_great_wonder()
Building_Type:is_small_wonder()
Building_Type:is_improvement()

-- Unit_Type methods.
Unit_Type:build_shield_cost()
Unit_Type:has_flag(flag)
Unit_Type:has_role(role)

--- find module
-- these functions are all prefixed with 'find.' when called
-- Example:
--    settler_type = find.unit_type('Settlers')
module find {
  Player player (player_id)
  City city (player, city_id)
  Unit unit (player, unit_id)
  Tile tile (nat_x, nat_y)

  Government government (government_id)
  Government government (name)
  Nation_Type nation_type (name)
  Nation_Type nation_type (nation_type_id)
  Building_Type building_type (name)
  Building_Type building_type (building_type_id)
  Unit_Type unit_type (name)
  Unit_Type unit_type (unit_type_id)
  Tech_Type tech_type (name)
  Tech_Type tech_type (tech_type_id)
  Terrain terrain (name)
  Terrain terrain (terrain_id)
}

--- signal module
module signal {
  void connect(signal_name, callback_name);
}

-- notify functions

-- Notify module implementation.
-- To send messages to the player
-- Takes a formatted string as last argument
-- Example:
--    notify.player(pplayer, "Year %d", year)
module notify {
  all(...)
  player(player, ...)
  event(player, tile, event, ...)
  embassies(player, ptile, event, ...)
}

-- utilities
-- generate random integer
int random (min, max)

-- actions

Unit create_unit (player, tile, unit_type, veteran_level, homecity, moves_left);
void create_city (player, tile, name);
void change_gold (player, with_amount);
Tech_Type give_technology (player, tech_type);

Rate this article:
Share this article: