Merged upstream/master

This commit is contained in:
Elvish_Hunter 2016-04-13 17:27:14 +02:00
commit 3c6d3e93d7
188 changed files with 2854 additions and 1919 deletions

View file

@ -11,7 +11,6 @@ compiler:
env:
- BUILD="-O0"
- BUILD="-O2"
- BUILD="C++14 -O2"
- BUILD="translations"
matrix:
@ -47,7 +46,7 @@ before_install:
- if [ "$BUILD" == "C++14 -O2" ]; then export WML_TEST_TIME=15; fi
- if [ "$BUILD" == "C++14 -O2" ]; then export CXXSTD="1y"; fi
- if [ "$BUILD" == "-O0" ]; then export EXTRA_FLAGS_RELEASE="-O0 -Wno-literal-suffix -Wno-deprecated-declarations"; fi
- if [ "$BUILD" == "-O0" ]; then export EXTRA_FLAGS_RELEASE="-O0 -Wno-deprecated-declarations"; fi
- if [[ "$BUILD" == "-O0" ]] && [[ "$CXX" == "clang++" ]]; then export EXTRA_FLAGS_RELEASE="-O0 -Wno-literal-suffix -Wno-deprecated-declarations -Wno-deprecated-register"; fi
- if [ "$BUILD" == "-O0" ]; then export PLAY_TEST=false; fi
- if [ "$BUILD" == "-O0" ]; then export MP_TEST=false; fi

View file

@ -18,7 +18,7 @@ endif(COMMAND cmake_policy)
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
# use our own version of FindBoost.cmake and other Find* scripts
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
#
# Options
@ -706,7 +706,7 @@ install(FILES l10n-track DESTINATION ${DATADIR})
#
configure_file(
"${CMAKE_MODULE_PATH}/uninstall.cmake.in"
"${CMAKE_SOURCE_DIR}/cmake/uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake"
IMMEDIATE @ONLY
)

View file

@ -4,6 +4,10 @@ Version 1.13.4+dev:
* Removed support for SDL 1.2. SDL 2 is now the only supported version.
* Terrains:
* Changed terrain code of Desert Mountains from Mdy to Mdd.
* User Interface:
* Various design improvements to GUI2 widgets
* New simpler GUI2 loading screen
* New colored cursor graphics
* WML engine:
* Fix some issues with [foreach]
* Fix some issues with backstab-like weapon specials
@ -16,6 +20,11 @@ Version 1.13.4+dev:
* New ~SCALE_INTO_SHARP(w,h) IPF which preserves aspect ratio, using
nearest neighbor scaling.
* Support delayed_variable_substitution= in [on_undo], [on_redo]
Note that this means $unit.x and $unit.y may not reflect the unit's
true location, so using [unstore_unit] on $unit may have unexpected effects.
This applies to $second_unit too. The $x1, $y1, $x2, $y2 variables work fine
though, so in most cases they can be used instead. Anything else in $unit
or $second_unit is also fine.
* formula= in SUF can now reference $other_unit via the formula variable "other"
* formula= now supported in location, side, and weapon filters
* Weapon filters now support number, parry, accuracy, and movement_used
@ -23,6 +32,9 @@ Version 1.13.4+dev:
uses full weapon filter.
* lua_function=var.member now works in SUF; however, 'var' still needs to
be a global variable.
* Added new keys name_generator, male_name_generator and female_name_generator
for the [race] tag to declare a context-free grammar to describe how names
are derived
* AiWML:
* Simplified aspect syntax which works for all aspects, present and future:
* All aspects with simple values can be specified as key=value
@ -120,6 +132,13 @@ Version 1.13.4+dev:
of the time in the overall schedule (eg, 1 would be dawn in the default
schedule). Optional second argument takes a time area ID, to set
local instead of global time.
* New wesnoth.add_fog and wesnoth.remove_fog functions allow changing fog
on the map. The [lift_fog] and [clear_fog] tags now use this.
* New wesnoth.add_sound_source, wesnoth.remove_sound_source, and
wesnoth.get_sound_source functions to allow manipulation of sound
sources. The [sound_source] and [remove_sound_source] now use these.
* New wesnoth.log function for printing log messages. The [wml_message]
and [deprecated_message] tags now use this.
* WML tables defined in Lua now accept string keys with array values
(where "array" is a table whose keys are all integers). This joins
the elements of the array with commas and produces a single string
@ -263,6 +282,8 @@ Version 1.13.4+dev:
* Miscellaneous and bug fixes:
* Resolve translated logo images not being used (bug #24357)
* Ported the "hexometer" tool from Bash to Python 3
* Recognize hotkey release events
* Allow changing keybindings for scrolling the map.
Version 1.13.4:
* Language and i18n:

View file

@ -233,7 +233,7 @@
# This is where the lich starts, so he will pick up this
# object immediately:
{FLAMING_SWORD 37 3 flaming-sword1}
{FLAMING_SWORD 37 3 flaming_sword1}
[recall]
id=Caladon
@ -667,7 +667,7 @@
# (because he will be near the top of the screen).
[/delay]
{FLAMING_SWORD $x1 $y1 flaming-sword2}
{FLAMING_SWORD $x1 $y1 flaming_sword2}
[object]
id=drop_staff
silent=yes
@ -978,7 +978,7 @@
equals=yes
[/variable]
[then]
{FLAMING_SWORD $sword_x $sword_y flaming-sword3}
{FLAMING_SWORD $sword_x $sword_y flaming_sword3}
{CLEAR_VARIABLE get_sword}
{CLEAR_VARIABLE sword_x}
{CLEAR_VARIABLE sword_y}
@ -1021,7 +1021,7 @@
equals=yes
[/variable]
[then]
{FLAMING_SWORD $sword_x $sword_y flaming-sword3}
{FLAMING_SWORD $sword_x $sword_y flaming_sword3}
{CLEAR_VARIABLE get_sword}
{CLEAR_VARIABLE sword_x}
{CLEAR_VARIABLE sword_y}

View file

@ -1058,6 +1058,9 @@
name = "Doug Rosvick (dlr365)"
wikiuser = "dlr365"
[/entry]
[entry]
name= "Dugi"
[/entry]
[entry]
name = "Duthlet"
[/entry]
@ -1357,6 +1360,10 @@
[entry]
name = "Ryan Henszey"
[/entry]
[entry]
name = "Ryan Roden-Corrent (rcorre)"
comment = "Hotkey release and scroll key rebinding"
[/entry]
[entry]
name = "Sachith Seneviratne (sachith500)"
email = "sachith500@gmail.com"
@ -1862,7 +1869,6 @@
[/entry]
[entry]
name = "Steven Panek (Espreon)"
comment = "Current maintainer"
email = "Majora700_AT_gmail_DOT_com"
wikiuser = "Espreon"
[/entry]
@ -1870,6 +1876,9 @@
name = "Thomas Hockings (Deusite)"
wikiuser = "Deusite"
[/entry]
[entry]
name = "Wedge009"
[/entry]
[/about]
[about]

View file

@ -13,6 +13,23 @@
#endif
#enddef
[hotkey]
command=scroll-up
key=UP
[/hotkey]
[hotkey]
command=scroll-down
key=DOWN
[/hotkey]
[hotkey]
command=scroll-left
key=LEFT
[/hotkey]
[hotkey]
command=scroll-right
key=RIGHT
[/hotkey]
[hotkey]
button=1
command="selectmoveaction"

File diff suppressed because one or more lines are too long

View file

@ -29,7 +29,7 @@
# If the text is too high it returns the top side.
# Rounding happens to the bottom side.
#define GUI__TEXT_VERTICALLY_CENTRED
"(if(text_height < height, (height - text_height - 2) / 2, 0))"
"(if(text_height < height, (height - text_height) / 2, 0))"
#enddef
#define GUI__CENTERED_TEXT FONT_SIZE FONT_STYLE FONT_COLOR
@ -279,6 +279,37 @@
[/row]
#enddef
#define GUI_VERTICAL_SPACER_LINE
[column]
border = "all"
border_size = 10
vertical_grow = true
[drawing]
definition = "default"
width = 1
height = (height)
[draw]
[line]
x1 = 0
y1 = 1
x2 = 0
y2 = (height - 1)
color = {GUI__FONT_COLOR_DISABLED__DEFAULT}
thickness = 1
[/line]
[/draw]
[/drawing]
[/column]
#enddef
###############################################################################
### ###
### Macros for the normal gui. ###
@ -307,5 +338,5 @@
#enddef
#define GUI_NORMAL__FONT_SIZE__TITLE
24
22
#enddef

View file

@ -13,7 +13,7 @@ horizontal_grow = "true"
# note we want a special button definition for this later.
[repeating_button]
id = "_half_page_up"
definition = "left_arrow"
definition = "scrollbar_left_arrow"
[/repeating_button]
[/column]
@ -34,7 +34,7 @@ horizontal_grow = "true"
# note we want a special button definition for this later.
[repeating_button]
id = "_half_page_down"
definition = "right_arrow"
definition = "scrollbar_right_arrow"
[/repeating_button]
[/column]

View file

@ -148,8 +148,9 @@
[draw]
{_GUI_STATE "background"
({_GUI_BORDER_COLOR_ALPHA {ALPHA}})
({_GUI_BORDER_COLOR_DARK_ALPHA {ALPHA}}) ("1, 10, 16, 255") "~GS(){IPF}"}
("128, 128, 128, {ALPHA}") # Same as GUI__FONT_COLOR_DISABLED__DEFAULT, but with an alpha componant
("89, 89, 89, {ALPHA}")
("1, 10, 16, 255") "~GS(){IPF}"}
{GUI__CENTERED_TEXT ({FONT_SIZE}) () ({GUI__FONT_COLOR_DISABLED__TITLE})}

View file

@ -3,43 +3,27 @@
### Definition of a horizontal scrollbar.
###
#define _GUI_STATE GROOVE_LEFT GROOVE_RIGHT POSITIONER_LEFT POSITIONER_RIGHT IMAGE_SUFFIX IPF
#define _GUI_STATE POSITIONER_LEFT IMAGE_SUFFIX IPF
[draw]
#
# Groove
#
[image]
# 4 pixels wide
[rectangle]
x = 0
y = 0
name = "buttons/scrollbars/scrollgroove-left.png{IPF}"
[/image]
[image]
x = {GROOVE_LEFT}
y = 0
w = "(if(width - {GROOVE_LEFT} - {GROOVE_RIGHT} < 0
, 0, width - {GROOVE_LEFT} - {GROOVE_RIGHT}))"
h = 0
resize_mode = "stretch"
name = "buttons/scrollbars/scrollgroove-horizontal.png{IPF}"
[/image]
[image]
# 5 pixels wide
x = "(width - {GROOVE_RIGHT})"
y = 0
name = "buttons/scrollbars/scrollgroove-right.png{IPF}"
[/image]
w = "(width)"
h = "(height)"
fill_color = "4, 4, 4, 255"
[/rectangle]
#
# Positioner
#
[image]
# 5 pixels wide
# 5 pixels high
x = "(positioner_offset)"
y = 0
name = "buttons/scrollbars/scrollleft{IMAGE_SUFFIX}{IPF}"
@ -49,15 +33,15 @@
x = "(positioner_offset + {POSITIONER_LEFT})"
y = 0
w = "(
if(positioner_length - {POSITIONER_LEFT} - {POSITIONER_RIGHT} < 0
, 0, positioner_length - {POSITIONER_LEFT} - {POSITIONER_RIGHT}))"
if(positioner_length - {POSITIONER_LEFT} < 0
, 0, positioner_length - {POSITIONER_LEFT}))"
resize_mode = "stretch"
name = "buttons/scrollbars/scrollhorizontal{IMAGE_SUFFIX}{IPF}"
[/image]
[image]
# 5 pixels wide
x = "(positioner_offset + positioner_length - {POSITIONER_RIGHT})"
# 5 pixels high
x = "(positioner_offset + positioner_length)"
y = 0
name = "buttons/scrollbars/scrollright{IMAGE_SUFFIX}{IPF}"
[/image]
@ -65,7 +49,7 @@ if(positioner_length - {POSITIONER_LEFT} - {POSITIONER_RIGHT} < 0
[/draw]
#enddef
#define _GUI_RESOLUTION RESOLUTION WIDTH HEIGHT POSITIONER_LENGHT GROOVE_LEFT GROOVE_RIGHT POSITIONER_LEFT POSITIONER_RIGHT IPF
#define _GUI_RESOLUTION RESOLUTION WIDTH HEIGHT POSITIONER_LENGHT POSITIONER_LEFT IPF
[resolution]
{RESOLUTION}
@ -74,7 +58,7 @@ if(positioner_length - {POSITIONER_LEFT} - {POSITIONER_RIGHT} < 0
min_height = {HEIGHT}
default_width = {WIDTH}
default_height = {HEIGHT}
default_height = 15
max_width = 0
max_height = {HEIGHT}
@ -85,19 +69,19 @@ if(positioner_length - {POSITIONER_LEFT} - {POSITIONER_RIGHT} < 0
right_offset = 0
[state_enabled]
{_GUI_STATE ({GROOVE_LEFT}) ({GROOVE_RIGHT}) ({POSITIONER_LEFT}) ({POSITIONER_RIGHT}) ".png" ({IPF}) }
{_GUI_STATE ({POSITIONER_LEFT}) ".png" ({IPF}) }
[/state_enabled]
[state_disabled]
{_GUI_STATE ({GROOVE_LEFT}) ({GROOVE_RIGHT}) ({POSITIONER_LEFT}) ({POSITIONER_RIGHT}) ".png~GS()" ({IPF}) }
{_GUI_STATE ({POSITIONER_LEFT}) ".png~GS()" ({IPF}) }
[/state_disabled]
[state_pressed]
{_GUI_STATE ({GROOVE_LEFT}) ({GROOVE_RIGHT}) ({POSITIONER_LEFT}) ({POSITIONER_RIGHT}) "-pressed.png" ({IPF}) }
{_GUI_STATE ({POSITIONER_LEFT}) "-pressed.png" ({IPF}) }
[/state_pressed]
[state_focused]
{_GUI_STATE ({GROOVE_LEFT}) ({GROOVE_RIGHT}) ({POSITIONER_LEFT}) ({POSITIONER_RIGHT}) "-active.png" ({IPF}) }
{_GUI_STATE ({POSITIONER_LEFT}) "-active.png" ({IPF}) }
[/state_focused]
[/resolution]
#enddef
@ -109,7 +93,7 @@ if(positioner_length - {POSITIONER_LEFT} - {POSITIONER_RIGHT} < 0
# Note a scrollbar is normally sized by the item that "masters" it
# that's why the default height is rather low.
{_GUI_RESOLUTION () 20 25 11 4 5 5 5 ()}
{_GUI_RESOLUTION () 20 25 11 2 ()}
[/horizontal_scrollbar_definition]
@ -120,7 +104,7 @@ if(positioner_length - {POSITIONER_LEFT} - {POSITIONER_RIGHT} < 0
# Note a scrollbar is normally sized by the item that "masters" it
# that's why the default height is rather low.
{_GUI_RESOLUTION () 20 25 11 4 5 5 5 "~O(65%)"}
{_GUI_RESOLUTION () 20 25 11 5 "~O(65%)"}
[/horizontal_scrollbar_definition]

View file

@ -132,6 +132,24 @@
#define _GUI_UNIT_PREVIEW_PANE_MINIMAL
[grid]
[row]
grow_factor = 0
[column]
border = "bottom"
border_size = 5
horizontal_alignment = "center"
vertical_alignment = "center"
[image]
id = "type_image"
definition = "default"
[/image]
[/column]
[/row]
[row]
grow_factor = 0
@ -153,51 +171,64 @@
[row]
grow_factor = 0
[column]
border = "bottom"
border_size = 5
vertical_grow = "true"
horizontal_grow = "true"
[grid]
[label]
id = "type_name"
wrap = "true"
[/label]
[row]
grow_factor = 1
[/column]
[column]
border = "right,bottom"
border_size = 5
horizontal_alignment = "left"
[/row]
[row]
grow_factor = 0
[label]
id = "type_level"
[/label]
[column]
border = "right,bottom"
border_size = 5
horizontal_alignment = "left"
[/column]
[label]
id = "type_level"
[/label]
[column]
border = "right,bottom"
border_size = 5
horizontal_alignment = "left"
[/column]
[image]
id = "type_race"
[/image]
[/row]
[/column]
[row]
grow_factor = 0
[column]
border = "bottom"
border_size = 5
horizontal_alignment = "left"
[column]
border = "right,bottom"
border_size = 5
horizontal_alignment = "left"
[image]
id = "type_alignment"
[/image]
[label]
id = "type_race"
[/label]
[/column]
[/column]
[/row]
[/row]
[/grid]
[row]
grow_factor = 0
[column]
border = "right,bottom"
border_size = 5
horizontal_alignment = "left"
[label]
id = "type_alignment"
[/label]
[/column]

View file

@ -26,12 +26,6 @@
fixed_width = "true"
[/linked_group]
[linked_group]
id = "tree_name"
fixed_width = "true"
fixed_height = "true"
[/linked_group]
[tooltip]
id = "tooltip"
[/tooltip]
@ -373,7 +367,7 @@
[label]
id = "name"
definition = "default"
linked_group = "tree_name"
linked_group = "name"
[/label]
[/column]

View file

@ -4,398 +4,406 @@
###
[window]
id = "custom_tod"
description = "Custom ToD schedules dialog."
id = "custom_tod"
description = "Custom ToD schedules dialog."
[resolution]
definition = "default"
[resolution]
definition = "default"
automatic_placement = "true"
vertical_placement = "center"
horizontal_placement = "center"
automatic_placement = "true"
vertical_placement = "center"
horizontal_placement = "center"
[tooltip]
id = "tooltip"
[/tooltip]
[tooltip]
id = "tooltip"
[/tooltip]
[helptip]
id = "tooltip"
[/helptip]
[helptip]
id = "tooltip"
[/helptip]
[linked_group]
id = "labels"
fixed_width = "true"
[/linked_group]
[linked_group]
id = "labels"
fixed_width = "true"
[/linked_group]
[linked_group]
id = "tod_index"
fixed_width = "true"
[/linked_group]
[linked_group]
id = "tod_index"
fixed_width = "true"
[/linked_group]
[grid]
[row]
grow_factor = 0
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "title"
label = _ "Custom Time Schedule"
[/label]
[/column]
[/row]
[row]
grow_factor = 0
[column]
horizontal_alignment = "left"
[grid]
[row]
grow_factor = 0
[column]
horizontal_grow = "true"
[grid]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "Name:"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[text_box]
id = "tod_name"
definition = "default"
[/text_box]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[image]
id = "current_tod_image"
definition = "default"
[/image]
[/column]
[/row]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "ID:"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[text_box]
id = "tod_id"
definition = "default"
[/text_box]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[image]
id = "current_tod_mask"
definition = "default"
[/image]
[/column]
[/row]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "Metadata:"
[/label]
[/column]
[column]
horizontal_alignment = "left"
[grid]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[button]
id = "image_button"
definition = "default"
label = _ "Image"
[/button]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[button]
id = "mask_button"
definition = "default"
label = _ "Mask"
[/button]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[button]
id = "sound_button"
definition = "default"
label = _ "Sound"
[/button]
[/column]
[/row]
[/grid]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[label]
id = "current_sound"
definition = "default"
[/label]
[/column]
[/row]
[/grid]
[/column]
[/row]
[row]
[column]
[grid]
[row]
grow_factor = 0
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "Lawful Bonus:"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[slider]
id = "lawful_bonus"
definition = "default"
best_slider_length = 512
minimum_value = -100
maximum_value = 100
step_size = 5
[/slider]
[/column]
[/row]
[row]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "Red:"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[slider]
id = "tod_red"
definition = "default"
best_slider_length = 512
minimum_value = -255
maximum_value = 255
step_size = 1
[/slider]
[/column]
[/row]
[row]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "Green:"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[slider]
id = "tod_green"
definition = "default"
best_slider_length = 512
minimum_value = -255
maximum_value = 255
step_size = 1
[/slider]
[/column]
[/row]
[row]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "Blue:"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[slider]
id = "tod_blue"
definition = "default"
best_slider_length = 512
minimum_value = -255
maximum_value = 255
step_size = 1
[/slider]
[/column]
[/row]
[/grid]
[/column]
[/row]
[/grid]
[/column]
[/row]
[row]
grow_factor = 1
[column]
horizontal_grow = "true"
[grid]
[row]
grow_factor = 1
[column]
horizontal_alignment = "left"
[grid]
[row]
grow_factor = 1
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[button]
id = "previous_tod"
definition = "left_arrow"
linked_group = "tod_index"
label = _ "Previous"
[/button]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
id = "tod_number"
definition = "default"
linked_group = "tod_index"
[/label]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[button]
id = "next_tod"
definition = "right_arrow"
linked_group = "tod_index"
label = _ "Next"
[/button]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[button]
id = "new"
definition = "add"
label = _ "New ToD"
[/button]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[button]
id = "delete"
definition = "delete"
label = _ "Delete ToD"
[/button]
[/column]
[/row]
[/grid]
[/column]
[column]
horizontal_alignment = "right"
[grid]
[row]
grow_factor = 1
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[button]
id = "save"
definition = "default"
label = _ "OK"
[/button]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[button]
id = "cancel"
definition = "default"
label = _ "Cancel"
[/button]
[/column]
[/row]
[/grid]
[/column]
[/row]
[/grid]
[/column]
[/row]
[/grid]
[/resolution]
[grid]
[row]
grow_factor = 0
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "title"
label = _ "Custom Time Schedule"
[/label]
[/column]
[/row]
[row]
grow_factor = 0
[column]
horizontal_grow = "true"
[grid]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "Name:"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[text_box]
id = "tod_name"
definition = "default"
[/text_box]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[image]
id = "current_tod_image"
definition = "default"
[/image]
[/column]
[/row]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "ID:"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[text_box]
id = "tod_id"
definition = "default"
[/text_box]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[image]
id = "current_tod_mask"
definition = "default"
[/image]
[/column]
[/row]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "Metadata:"
[/label]
[/column]
[column]
horizontal_alignment = "left"
[grid]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[button]
id = "image_button"
definition = "default"
label = _ "Image"
[/button]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[button]
id = "mask_button"
definition = "default"
label = _ "Mask"
[/button]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[button]
id = "sound_button"
definition = "default"
label = _ "Sound"
[/button]
[/column]
[/row]
[/grid]
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[label]
id = "current_sound"
definition = "default"
[/label]
[/column]
[/row]
[/grid]
[/column]
[/row]
[row]
[column]
[grid]
[row]
grow_factor = 0
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "Lawful Bonus:"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[slider]
id = "lawful_bonus"
definition = "default"
best_slider_length = 512
minimum_value = -100
maximum_value = 100
step_size = 5
[/slider]
[/column]
[/row]
[row]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "Red:"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[slider]
id = "tod_red"
definition = "default"
best_slider_length = 512
minimum_value = -255
maximum_value = 255
step_size = 1
[/slider]
[/column]
[/row]
[row]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "Green:"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[slider]
id = "tod_green"
definition = "default"
best_slider_length = 512
minimum_value = -255
maximum_value = 255
step_size = 1
[/slider]
[/column]
[/row]
[row]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
linked_group = "labels"
label = _ "Blue:"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[slider]
id = "tod_blue"
definition = "default"
best_slider_length = 512
minimum_value = -255
maximum_value = 255
step_size = 1
[/slider]
[/column]
[/row]
[/grid]
[/column]
[/row]
[row]
grow_factor = 1
[column]
horizontal_grow = "true"
[grid]
[row]
grow_factor = 1
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[button]
id = "previous_tod"
definition = "left_arrow"
linked_group = "tod_index"
label = _ "Previous"
[/button]
[/column]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
id = "tod_number"
definition = "default"
linked_group = "tod_index"
[/label]
[/column]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[button]
id = "next_tod"
definition = "right_arrow"
linked_group = "tod_index"
label = _ "Next"
[/button]
[/column]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[button]
id = "new"
definition = "add"
label = _ "New ToD"
[/button]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "left"
[button]
id = "delete"
definition = "delete"
label = _ "Delete ToD"
[/button]
[/column]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "right"
[button]
id = "ok"
definition = "default"
label = _ "OK"
[/button]
[/column]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "right"
[button]
id = "cancel"
definition = "default"
label = _ "Cancel"
[/button]
[/column]
[/row]
[/grid]
[/column]
[/row]
[/grid]
[/resolution]
[/window]

View file

@ -45,7 +45,7 @@
[column]
[spacer]
height = "((screen_height - if(screen_height < 800, 400, 0)) / 4)"
height = "((screen_height - if(screen_height < 800, 200, 0)) / 3.5)"
[/spacer]
[/column]
@ -75,7 +75,7 @@
{_GUI_PADDING}
[row]
grow_factor = 1
grow_factor = 2
[column]
grow_factor = 1
@ -100,22 +100,20 @@
grow_factor = 1
border = "all"
border_size = 5
horizontal_grow = "true"
horizontal_alignment = "center"
vertical_alignment = "center"
[label]
text_alignment = "center"
definition = "default_large"
id = "status"
label = _ "Loading..."
[/label]
[image]
definition = "decoration"
label = "misc/loadscreen_decor.png"
[/image]
[/column]
[/row]
[row]
grow_factor = 0
grow_factor = 1
[column]
grow_factor = 1
@ -142,13 +140,15 @@
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "center"
horizontal_grow = "true"
vertical_alignment = "center"
[image]
definition = "decoration"
label = "misc/loadscreen_decor.png"
[/image]
[label]
text_alignment = "center"
definition = "default_large"
id = "status"
label = _ "Loading..."
[/label]
[/column]

View file

@ -104,7 +104,7 @@
#define GAMELISTBOX
border = "all"
border_size = 5
[listbox]
id = "game_list"
definition = "default"
@ -679,7 +679,7 @@ border_size = 5
border_size = 5
[button]
id = "quit"
definition = "default"
definition = "large"
label = _ "Log Out"
[/button]
{VERTICAL_SEP}
@ -687,7 +687,7 @@ border_size = 5
border_size = 5
[button]
id = "show_preferences"
definition = "default"
definition = "large"
label = _ "Preferences"
[/button]
{VERTICAL_SEP}
@ -695,7 +695,7 @@ border_size = 5
border_size = 5
[button]
id = "refresh"
definition = "default"
definition = "large"
label = _ "Refresh"
[/button]
{VERTICAL_SEP}
@ -703,7 +703,7 @@ border_size = 5
border_size = 10
[button]
id = "create"
definition = "default"
definition = "large"
label = _ "Create Game"
[/button]
{VERTICAL_SEP}
@ -711,7 +711,7 @@ border_size = 5
border_size = 5
[button]
id = "join_global"
definition = "default"
definition = "large"
label = _ "Join"
[/button]
{VERTICAL_SEP}
@ -719,7 +719,7 @@ border_size = 5
border_size = 5
[button]
id = "observe_global"
definition = "default"
definition = "large"
label = _ "Observe"
[/button]
{VERTICAL_SEP}
@ -727,7 +727,7 @@ border_size = 5
border_size = 5
[toggle_button]
id = "skip_replay"
definition = "default"
definition = "large"
label = _ "Quick replay"
[/toggle_button]
# wmlxgettext: [column]
@ -794,8 +794,10 @@ border_size = 5
[column]
horizontal_grow = "true"
vertical_grow = "true"
border = "all"
border_size = 5
{GUI_FORCE_OUTLINED_WIDGET_MINIMUM_SIZE
0 "((screen_height * 30) / 100)"
0 "((screen_height * if(screen_height < 800, 30, 50)) / 100)"
5 1 {GUI__BORDER_COLOR_BRIGHT} (
{GAMELISTBOX}
)}

View file

@ -253,7 +253,7 @@
[slider]
id = "scaling_slider"
definition = "minimal"
minimum_value,maximum_value=100,200
minimum_value,maximum_value=80,200
step_size=5
tooltip= _ "Set the scaling factor of fonts"
[/slider]

View file

@ -162,34 +162,7 @@
{_GUI_BIG_ATTACKER_PANEL}
[/column]
[column]
border = "all"
border_size = 10
vertical_grow = true
[drawing]
definition = "default"
width = 1
height = (height)
[draw]
[line]
x1 = 0
y1 = 1
x2 = 0
y2 = (height - 1)
color = {GUI__FONT_COLOR_DISABLED__DEFAULT}
thickness = 1
[/line]
[/draw]
[/drawing]
[/column]
{GUI_VERTICAL_SPACER_LINE}
[column]
grow_factor = 1

View file

@ -5,12 +5,19 @@
# provide different font orders: one just has to install the
# missing fonts without needing to change the gmo files
order=_ "DejaVuSans.ttf,Andagii.ttf,DroidSansJapanese.ttf,DroidSansFallbackFull.ttf,Junicode-Regular.ttf"
family_order=_ "DejaVu Sans,Andagii,Droid Sans Japanese,Droid Sans Fallback,Junicode"
family_order=_ "Lato"
# Used by GUI2 only, hence no [font] blocks for these. The font files are
# also automatically determined.
family_order_monospace=_ "DejaVu Sans Mono"
[font]
name="Lato-Regular.ttf"
bold_name="Lato-Bold.ttf"
italic_name="Lato-Italic.ttf"
codepoints="32-126,160-831,834,837-879,885,890-893,900-902,904-906,908,910-929,931-974,976-1158,1160-1299,3647,7424-7626,7678-7835,7838,7840-7929,7936-7957,7960-7965,7968-8005,8008-8013,8016-8023,8025,8027,8029,8031-8048,8050,8052,8054,8056,8058,8060,8064-8116,8118-8122,8124-8125,8127-8132,8134-8136,8138,8140-8146,8150-8154,8157-8162,8164-8170,8172-8173,8178-8180,8182-8184,8186,8188,8190,8194-8208,8210-8226,8230,8239-8240,8242-8244,8249-8250,8252-8254,8260,8286-8287,8304-8305,8308-8340,8352-8373,8376-8378,8413,8453,8467,8470-8471,8480,8482,8494,8498,8525-8526,8531-8543,8579-8580,8592-8601,8616,8706,8710,8719,8721-8722,8725,8729-8730,8734-8735,8745,8747,8776,8800-8801,8804-8805,8962,8976,8992-8993,9312-9331,9450-9460,9471-9472,9474,9484,9488,9492,9496,9633,9642-9643,9674-9676,9679,9702,9728,9788,9833,10102-10111,11360-11372,11380-11383,11799,42775-42778,42784-42785,63743,64256-64260,65056-65059,65279"
[/font]
[font]
name="DejaVuSans.ttf"
bold_name="DejaVuSans-Bold.ttf"

259
data/lua/wml-flow.lua Normal file
View file

@ -0,0 +1,259 @@
local helper = wesnoth.require "lua/helper.lua"
local utils = wesnoth.require "lua/wml-utils.lua"
local wml_actions = wesnoth.wml_actions
function wml_actions.command(cfg)
utils.handle_event_commands(cfg, "plain")
end
-- we can't create functions with names that are Lua keywords (eg if, while)
-- instead, we store the following anonymous functions directly into
-- the table, using the [] operator, rather than by using the point syntax
wml_actions["if"] = function(cfg)
if not (helper.get_child(cfg, 'then') or helper.get_child(cfg, 'elseif') or helper.get_child(cfg, 'else')) then
helper.wml_error("[if] didn't find any [then], [elseif], or [else] children.")
end
if wesnoth.eval_conditional(cfg) then -- evaluate [if] tag
for then_child in helper.child_range(cfg, "then") do
local action = utils.handle_event_commands(then_child, "conditional")
if action ~= "none" then break end
end
return -- stop after executing [then] tags
end
for elseif_child in helper.child_range(cfg, "elseif") do
if wesnoth.eval_conditional(elseif_child) then -- we'll evaluate the [elseif] tags one by one
for then_tag in helper.child_range(elseif_child, "then") do
local action = utils.handle_event_commands(then_tag, "conditional")
if action ~= "none" then break end
end
return -- stop on first matched condition
end
end
-- no matched condition, try the [else] tags
for else_child in helper.child_range(cfg, "else") do
local action = utils.handle_event_commands(else_child, "conditional")
if action ~= "none" then break end
end
end
wml_actions["while"] = function( cfg )
if helper.child_count(cfg, "do") == 0 then
helper.wml_error "[while] does not contain any [do] tags"
end
-- execute [do] up to 65536 times
for i = 1, 65536 do
if wesnoth.eval_conditional( cfg ) then
for do_child in helper.child_range( cfg, "do" ) do
local action = utils.handle_event_commands(do_child, "loop")
if action == "break" then
utils.set_exiting("none")
return
elseif action == "continue" then
utils.set_exiting("none")
break
elseif action ~= "none" then
return
end
end
else return end
end
end
wml_actions["break"] = function(cfg)
utils.set_exiting("break")
end
wml_actions["return"] = function(cfg)
utils.set_exiting("return")
end
function wml_actions.continue(cfg)
utils.set_exiting("continue")
end
wesnoth.wml_actions["for"] = function(cfg)
if helper.child_count(cfg, "do") == 0 then
helper.wml_error "[for] does not contain any [do] tags"
end
local loop_lim = {}
local first
if cfg.array ~= nil then
if cfg.reverse then
first = wesnoth.get_variable(cfg.array .. ".length") - 1
loop_lim.last = 0
loop_lim.step = -1
else
first = 0
loop_lim.last = '$($' .. cfg.array .. ".length - 1)"
loop_lim.step = 1
end
else
-- Get a literal config to fetch end and step;
-- this done is to delay expansion of variables
local cfg_lit = helper.literal(cfg)
first = cfg.start or 0
loop_lim.last = cfg_lit["end"] or first
if cfg.step then loop_lim.step = cfg_lit.step end
end
loop_lim = wesnoth.tovconfig(loop_lim)
if loop_lim.step == 0 then -- Sanity check
helper.wml_error("[for] has a step of 0!")
end
if (first < loop_lim.last and loop_lim.step <= 0) or (first > loop_lim.last and loop_lim.step >= 0) then
-- Sanity check: If they specify something like start,end,step=1,4,-1
-- then we do nothing
return
end
local i_var = cfg.variable or "i"
local save_i = utils.start_var_scope(i_var)
wesnoth.set_variable(i_var, first)
local function loop_condition()
local sentinel = loop_lim.last
if loop_lim.step then
sentinel = sentinel + loop_lim.step
elseif loop_lim.last < first then
sentinel = sentinel - 1
else
sentinel = sentinel + 1
end
if loop_lim.step > 0 then
return wesnoth.get_variable(i_var) < sentinel
else
return wesnoth.get_variable(i_var) > sentinel
end
end
while loop_condition() do
for do_child in helper.child_range( cfg, "do" ) do
local action = utils.handle_event_commands(do_child, "loop")
if action == "break" then
utils.set_exiting("none")
goto exit
elseif action == "continue" then
utils.set_exiting("none")
break
elseif action ~= "none" then
goto exit
end
end
wesnoth.set_variable(i_var, wesnoth.get_variable(i_var) + loop_lim.step)
end
::exit::
utils.end_var_scope(i_var, save_i)
end
wml_actions["repeat"] = function(cfg)
if helper.child_count(cfg, "do") == 0 then
helper.wml_error "[repeat] does not contain any [do] tags"
end
local times = cfg.times or 1
for i = 1, times do
for do_child in helper.child_range( cfg, "do" ) do
local action = utils.handle_event_commands(do_child, "loop")
if action == "break" then
utils.set_exiting("none")
return
elseif action == "continue" then
utils.set_exiting("none")
break
elseif action ~= "none" then
return
end
end
end
end
function wml_actions.foreach(cfg)
if helper.child_count(cfg, "do") == 0 then
helper.wml_error "[foreach] does not contain any [do] tags"
end
local array_name = cfg.variable or helper.wml_error "[foreach] missing required variable= attribute"
local array = helper.get_variable_array(array_name)
if #array == 0 then return end -- empty and scalars unwanted
local item_name = cfg.item_var or "this_item"
local this_item = utils.start_var_scope(item_name) -- if this_item is already set
local i_name = cfg.index_var or "i"
local i = utils.start_var_scope(i_name) -- if i is already set
local array_length = wesnoth.get_variable(array_name .. ".length")
for index, value in ipairs(array) do
-- Some protection against external modification
-- It's not perfect, though - it'd be nice if *any* change could be detected
if array_length ~= wesnoth.get_variable(array_name .. ".length") then
helper.wml_error("WML array length changed during [foreach] iteration")
end
wesnoth.set_variable(item_name, value)
-- set index variable
wesnoth.set_variable(i_name, index-1) -- here -1, because of WML array
-- perform actions
for do_child in helper.child_range(cfg, "do") do
local action = utils.handle_event_commands(do_child, "loop")
if action == "break" then
utils.set_exiting("none")
goto exit
elseif action == "continue" then
utils.set_exiting("none")
break
elseif action ~= "none" then
goto exit
end
end
-- set back the content, in case the author made some modifications
if not cfg.readonly then
array[index] = wesnoth.get_variable(item_name)
end
end
::exit::
-- house cleaning
utils.end_var_scope(item_name, this_item)
utils.end_var_scope(i_name, i)
--[[
This forces the readonly key to be taken literally.
If readonly=yes, then this line guarantees that the array
is unchanged after the [foreach] loop ends.
If readonly=no, then this line updates the array with any
changes the user has applied through the $this_item
variable (or whatever variable was given in item_var).
Note that altering the array via indexing (with the index_var)
is not supported; any such changes will be reverted by this line.
]]
helper.set_variable_array(array_name, array)
end
function wml_actions.switch(cfg)
local var_value = wesnoth.get_variable(cfg.variable)
local found = false
-- Execute all the [case]s where the value matches.
for v in helper.child_range(cfg, "case") do
for w in utils.split(v.value) do
if w == tostring(var_value) then
local action = utils.handle_event_commands(v, "switch")
found = true
if action ~= "none" then goto exit end
break
end
end
end
::exit::
-- Otherwise execute [else] statements.
if not found then
for v in helper.child_range(cfg, "else") do
local action = utils.handle_event_commands(v, "switch")
if action ~= "none" then break end
end
end
end

View file

@ -11,10 +11,16 @@ function wesnoth.game_events.on_save()
return {}
end
wesnoth.require "lua/wml-flow.lua"
wesnoth.require "lua/wml/objectives.lua"
wesnoth.require "lua/wml/items.lua"
wesnoth.require "lua/wml/message.lua"
wesnoth.require "lua/wml/object.lua"
wesnoth.require "lua/wml/modify_unit.lua"
wesnoth.require "lua/wml/harm_unit.lua"
wesnoth.require "lua/wml/find_path.lua"
wesnoth.require "lua/wml/endlevel.lua"
wesnoth.require "lua/wml/random_placement.lua"
local helper = wesnoth.require "lua/helper.lua"
local location_set = wesnoth.require "lua/location_set.lua"
@ -260,262 +266,6 @@ function wml_actions.music(cfg)
wesnoth.set_music(cfg)
end
function wml_actions.command(cfg)
utils.handle_event_commands(cfg, "plain")
end
-- we can't create functions with names that are Lua keywords (eg if, while)
-- instead, we store the following anonymous functions directly into
-- the table, using the [] operator, rather than by using the point syntax
wml_actions["if"] = function(cfg)
if not (helper.get_child(cfg, 'then') or helper.get_child(cfg, 'elseif') or helper.get_child(cfg, 'else')) then
helper.wml_error("[if] didn't find any [then], [elseif], or [else] children.")
end
if wesnoth.eval_conditional(cfg) then -- evaluate [if] tag
for then_child in helper.child_range(cfg, "then") do
local action = utils.handle_event_commands(then_child, "conditional")
if action ~= "none" then break end
end
return -- stop after executing [then] tags
end
for elseif_child in helper.child_range(cfg, "elseif") do
if wesnoth.eval_conditional(elseif_child) then -- we'll evaluate the [elseif] tags one by one
for then_tag in helper.child_range(elseif_child, "then") do
local action = utils.handle_event_commands(then_tag, "conditional")
if action ~= "none" then break end
end
return -- stop on first matched condition
end
end
-- no matched condition, try the [else] tags
for else_child in helper.child_range(cfg, "else") do
local action = utils.handle_event_commands(else_child, "conditional")
if action ~= "none" then break end
end
end
wml_actions["while"] = function( cfg )
if helper.child_count(cfg, "do") == 0 then
helper.wml_error "[while] does not contain any [do] tags"
end
-- execute [do] up to 65536 times
for i = 1, 65536 do
if wesnoth.eval_conditional( cfg ) then
for do_child in helper.child_range( cfg, "do" ) do
local action = utils.handle_event_commands(do_child, "loop")
if action == "break" then
utils.set_exiting("none")
return
elseif action == "continue" then
utils.set_exiting("none")
break
elseif action ~= "none" then
return
end
end
else return end
end
end
wml_actions["break"] = function(cfg)
utils.set_exiting("break")
end
wml_actions["return"] = function(cfg)
utils.set_exiting("return")
end
function wml_actions.continue(cfg)
utils.set_exiting("continue")
end
wesnoth.wml_actions["for"] = function(cfg)
if helper.child_count(cfg, "do") == 0 then
helper.wml_error "[for] does not contain any [do] tags"
end
local loop_lim = {}
local first
if cfg.array ~= nil then
if cfg.reverse then
first = wesnoth.get_variable(cfg.array .. ".length") - 1
loop_lim.last = 0
loop_lim.step = -1
else
first = 0
loop_lim.last = '$($' .. cfg.array .. ".length - 1)"
loop_lim.step = 1
end
else
-- Get a literal config to fetch end and step;
-- this done is to delay expansion of variables
local cfg_lit = helper.literal(cfg)
first = cfg.start or 0
loop_lim.last = cfg_lit["end"] or first
if cfg.step then loop_lim.step = cfg_lit.step end
end
loop_lim = wesnoth.tovconfig(loop_lim)
if loop_lim.step == 0 then -- Sanity check
helper.wml_error("[for] has a step of 0!")
end
if (first < loop_lim.last and loop_lim.step <= 0) or (first > loop_lim.last and loop_lim.step >= 0) then
-- Sanity check: If they specify something like start,end,step=1,4,-1
-- then we do nothing
return
end
local i_var = cfg.variable or "i"
local save_i = utils.start_var_scope(i_var)
wesnoth.set_variable(i_var, first)
local function loop_condition()
local sentinel = loop_lim.last
if loop_lim.step then
sentinel = sentinel + loop_lim.step
elseif loop_lim.last < first then
sentinel = sentinel - 1
else
sentinel = sentinel + 1
end
if loop_lim.step > 0 then
return wesnoth.get_variable(i_var) < sentinel
else
return wesnoth.get_variable(i_var) > sentinel
end
end
while loop_condition() do
for do_child in helper.child_range( cfg, "do" ) do
local action = utils.handle_event_commands(do_child, "loop")
if action == "break" then
utils.set_exiting("none")
goto exit
elseif action == "continue" then
utils.set_exiting("none")
break
elseif action ~= "none" then
goto exit
end
end
wesnoth.set_variable(i_var, wesnoth.get_variable(i_var) + loop_lim.step)
end
::exit::
utils.end_var_scope(i_var, save_i)
end
wml_actions["repeat"] = function(cfg)
if helper.child_count(cfg, "do") == 0 then
helper.wml_error "[repeat] does not contain any [do] tags"
end
local times = cfg.times or 1
for i = 1, times do
for do_child in helper.child_range( cfg, "do" ) do
local action = utils.handle_event_commands(do_child, "loop")
if action == "break" then
utils.set_exiting("none")
return
elseif action == "continue" then
utils.set_exiting("none")
break
elseif action ~= "none" then
return
end
end
end
end
function wml_actions.foreach(cfg)
if helper.child_count(cfg, "do") == 0 then
helper.wml_error "[foreach] does not contain any [do] tags"
end
local array_name = cfg.variable or helper.wml_error "[foreach] missing required variable= attribute"
local array = helper.get_variable_array(array_name)
if #array == 0 then return end -- empty and scalars unwanted
local item_name = cfg.item_var or "this_item"
local this_item = utils.start_var_scope(item_name) -- if this_item is already set
local i_name = cfg.index_var or "i"
local i = utils.start_var_scope(i_name) -- if i is already set
local array_length = wesnoth.get_variable(array_name .. ".length")
for index, value in ipairs(array) do
-- Some protection against external modification
-- It's not perfect, though - it'd be nice if *any* change could be detected
if array_length ~= wesnoth.get_variable(array_name .. ".length") then
helper.wml_error("WML array length changed during [foreach] iteration")
end
wesnoth.set_variable(item_name, value)
-- set index variable
wesnoth.set_variable(i_name, index-1) -- here -1, because of WML array
-- perform actions
for do_child in helper.child_range(cfg, "do") do
local action = utils.handle_event_commands(do_child, "loop")
if action == "break" then
utils.set_exiting("none")
goto exit
elseif action == "continue" then
utils.set_exiting("none")
break
elseif action ~= "none" then
goto exit
end
end
-- set back the content, in case the author made some modifications
if not cfg.readonly then
array[index] = wesnoth.get_variable(item_name)
end
end
::exit::
-- house cleaning
utils.end_var_scope(item_name, this_item)
utils.end_var_scope(i_name, i)
--[[
This forces the readonly key to be taken literally.
If readonly=yes, then this line guarantees that the array
is unchanged after the [foreach] loop ends.
If readonly=no, then this line updates the array with any
changes the user has applied through the $this_item
variable (or whatever variable was given in item_var).
Note that altering the array via indexing (with the index_var)
is not supported; any such changes will be reverted by this line.
]]
helper.set_variable_array(array_name, array)
end
function wml_actions.switch(cfg)
local var_value = wesnoth.get_variable(cfg.variable)
local found = false
-- Execute all the [case]s where the value matches.
for v in helper.child_range(cfg, "case") do
for w in utils.split(v.value) do
if w == tostring(var_value) then
local action = utils.handle_event_commands(v, "switch")
found = true
if action ~= "none" then goto exit end
break
end
end
end
::exit::
-- Otherwise execute [else] statements.
if not found then
for v in helper.child_range(cfg, "else") do
local action = utils.handle_event_commands(v, "switch")
if action ~= "none" then break end
end
end
end
-- This is mainly for use in unit test macros, but maybe it can be useful elsewhere too
function wml_actions.test_condition(cfg)
local logger = cfg.logger or "warning"
@ -558,7 +308,7 @@ function wml_actions.test_condition(cfg)
if tag == "variable" then
explanation = string.format("%s\n\tNote: The variable %s currently has the value %q.", explanation, this_cfg.name, tostring(wesnoth.get_variable(this_cfg.name)))
end
wesnoth.wml_actions.wml_message{message = explanation, logger = logger}
wesnoth.log(logger, explanation, true)
return true
end
end
@ -748,77 +498,6 @@ function wml_actions.unhide_unit(cfg)
wml_actions.redraw {}
end
function wml_actions.modify_unit(cfg)
local unit_variable = "LUA_modify_unit"
local function handle_attributes(cfg, unit_path, toplevel)
for current_key, current_value in pairs(helper.shallow_parsed(cfg)) do
if type(current_value) ~= "table" and (not toplevel or current_key ~= "type") then
wesnoth.set_variable(string.format("%s.%s", unit_path, current_key), current_value)
end
end
end
local function handle_child(cfg, unit_path)
local children_handled = {}
local cfg = helper.shallow_parsed(cfg)
handle_attributes(cfg, unit_path)
for current_index, current_table in ipairs(cfg) do
local current_tag = current_table[1]
local tag_index = children_handled[current_tag] or 0
handle_child(current_table[2], string.format("%s.%s[%u]",
unit_path, current_tag, tag_index))
children_handled[current_tag] = tag_index + 1
end
end
local filter = helper.get_child(cfg, "filter") or helper.wml_error "[modify_unit] missing required [filter] tag"
local function handle_unit(unit_num)
local children_handled = {}
local unit_path = string.format("%s[%u]", unit_variable, unit_num)
local this_unit = wesnoth.get_variable(unit_path)
wesnoth.set_variable("this_unit", this_unit)
handle_attributes(cfg, unit_path, true)
for current_index, current_table in ipairs(helper.shallow_parsed(cfg)) do
local current_tag = current_table[1]
if current_tag == "filter" then
-- nothing
elseif current_tag == "object" or current_tag == "trait" or current_tag == "advancement" then
local unit = wesnoth.get_variable(unit_path)
unit = wesnoth.create_unit(unit)
wesnoth.add_modification(unit, current_tag, current_table[2])
unit = unit.__cfg;
wesnoth.set_variable(unit_path, unit)
else
local tag_index = children_handled[current_tag] or 0
handle_child(current_table[2], string.format("%s.%s[%u]",
unit_path, current_tag, tag_index))
children_handled[current_tag] = tag_index + 1
end
end
if cfg.type then
if cfg.type ~= "" then wesnoth.set_variable(unit_path .. ".advances_to", cfg.type) end
wesnoth.set_variable(unit_path .. ".experience", wesnoth.get_variable(unit_path .. ".max_experience"))
end
wml_actions.kill({ id = this_unit.id, animate = false })
wml_actions.unstore_unit { variable = unit_path }
end
wml_actions.store_unit { {"filter", filter}, variable = unit_variable }
local max_index = wesnoth.get_variable(unit_variable .. ".length") - 1
local this_unit = utils.start_var_scope("this_unit")
for current_unit = 0, max_index do
handle_unit(current_unit)
end
utils.end_var_scope("this_unit", this_unit)
wesnoth.set_variable(unit_variable)
end
function wml_actions.move_unit(cfg)
local coordinate_error = "invalid coordinate in [move_unit]"
local to_x = tostring(cfg.to_x or helper.wml_error(coordinate_error))
@ -949,207 +628,6 @@ function wml_actions.unpetrify(cfg)
end
end
function wml_actions.harm_unit(cfg)
local filter = helper.get_child(cfg, "filter") or helper.wml_error("[harm_unit] missing required [filter] tag")
-- we need to use shallow_literal field, to avoid raising an error if $this_unit (not yet assigned) is used
if not helper.shallow_literal(cfg).amount then helper.wml_error("[harm_unit] has missing required amount= attribute") end
local variable = cfg.variable -- kept out of the way to avoid problems
local _ = wesnoth.textdomain "wesnoth"
-- #textdomain wesnoth
local harmer
local function toboolean( value ) -- helper for animate fields
-- units will be animated upon leveling or killing, even
-- with special attacker and defender values
if value then return true
else return false end
end
local this_unit = utils.start_var_scope("this_unit")
for index, unit_to_harm in ipairs(wesnoth.get_units(filter)) do
if unit_to_harm.valid then
-- block to support $this_unit
wesnoth.set_variable ( "this_unit" ) -- clearing this_unit
wesnoth.set_variable("this_unit", unit_to_harm.__cfg) -- cfg field needed
local amount = tonumber(cfg.amount)
local animate = cfg.animate -- attacker and defender are special values
local delay = cfg.delay or 500
local kill = cfg.kill
local fire_event = cfg.fire_event
local primary_attack = helper.get_child(cfg, "primary_attack")
local secondary_attack = helper.get_child(cfg, "secondary_attack")
local harmer_filter = helper.get_child(cfg, "filter_second")
local experience = cfg.experience
local resistance_multiplier = tonumber(cfg.resistance_multiplier) or 1
if harmer_filter then harmer = wesnoth.get_units(harmer_filter)[1] end
-- end of block to support $this_unit
if animate then
if animate ~= "defender" and harmer and harmer.valid then
wesnoth.scroll_to_tile(harmer.x, harmer.y, true)
wml_actions.animate_unit {
flag = "attack",
hits = true,
with_bars = true,
T.filter { id = harmer.id },
T.primary_attack ( primary_attack ),
T.secondary_attack ( secondary_attack ),
T.facing { x = unit_to_harm.x, y = unit_to_harm.y },
}
end
wesnoth.scroll_to_tile(unit_to_harm.x, unit_to_harm.y, true)
end
-- the two functions below are taken straight from the C++ engine, utils.cpp and actions.cpp, with a few unuseful parts removed
-- may be moved in helper.lua in 1.11
local function round_damage( base_damage, bonus, divisor )
local rounding
if base_damage == 0 then return 0
else
if bonus < divisor or divisor == 1 then
rounding = divisor / 2 - 0
else
rounding = divisor / 2 - 1
end
return math.max( 1, math.floor( ( base_damage * bonus + rounding ) / divisor ) )
end
end
local function calculate_damage( base_damage, alignment, tod_bonus, resistance, modifier )
local damage_multiplier = 100
if alignment == "lawful" then
damage_multiplier = damage_multiplier + tod_bonus
elseif alignment == "chaotic" then
damage_multiplier = damage_multiplier - tod_bonus
elseif alignment == "liminal" then
damage_multiplier = damage_multiplier - math.abs( tod_bonus )
else -- neutral, do nothing
end
local resistance_modified = resistance * modifier
damage_multiplier = damage_multiplier * resistance_modified
local damage = round_damage( base_damage, damage_multiplier, 10000 ) -- if harmer.status.slowed, this may be 20000 ?
return damage
end
local damage = calculate_damage(
amount,
cfg.alignment or "neutral",
wesnoth.get_time_of_day( { unit_to_harm.x, unit_to_harm.y, true } ).lawful_bonus,
wesnoth.unit_resistance( unit_to_harm, cfg.damage_type or "dummy" ),
resistance_multiplier
)
if unit_to_harm.hitpoints <= damage then
if kill == false then damage = unit_to_harm.hitpoints - 1
else damage = unit_to_harm.hitpoints
end
end
unit_to_harm.hitpoints = unit_to_harm.hitpoints - damage
local text = string.format("%d%s", damage, "\n")
local add_tab = false
local gender = unit_to_harm.__cfg.gender
local function set_status(name, male_string, female_string, sound)
if not cfg[name] or unit_to_harm.status[name] then return end
if gender == "female" then
text = string.format("%s%s%s", text, tostring(female_string), "\n")
else
text = string.format("%s%s%s", text, tostring(male_string), "\n")
end
unit_to_harm.status[name] = true
add_tab = true
if animate and sound then -- for unhealable, that has no sound
wesnoth.play_sound (sound)
end
end
if not unit_to_harm.status.unpoisonable then
set_status("poisoned", _"poisoned", _"female^poisoned", "poison.ogg")
end
set_status("slowed", _"slowed", _"female^slowed", "slowed.wav")
set_status("petrified", _"petrified", _"female^petrified", "petrified.ogg")
set_status("unhealable", _"unhealable", _"female^unhealable")
-- Extract unit and put it back to update animation if status was changed
wesnoth.extract_unit(unit_to_harm)
wesnoth.put_unit(unit_to_harm)
if add_tab then
text = string.format("%s%s", "\t", text)
end
if animate and animate ~= "attacker" then
if harmer and harmer.valid then
wml_actions.animate_unit {
flag = "defend",
hits = true,
with_bars = true,
T.filter { id = unit_to_harm.id },
T.primary_attack ( primary_attack ),
T.secondary_attack ( secondary_attack ),
T.facing { x = harmer.x, y = harmer.y },
}
else
wml_actions.animate_unit {
flag = "defend",
hits = true,
with_bars = true,
T.filter { id = unit_to_harm.id },
T.primary_attack ( primary_attack ),
T.secondary_attack ( secondary_attack ),
}
end
end
wesnoth.float_label( unit_to_harm.x, unit_to_harm.y, string.format( "<span foreground='red'>%s</span>", text ) )
local function calc_xp( level ) -- to calculate the experience in case of kill
if level == 0 then return 4
else return level * 8 end
end
if experience ~= false and harmer and harmer.valid and wesnoth.is_enemy( unit_to_harm.side, harmer.side ) then -- no XP earned for harming friendly units
if kill ~= false and unit_to_harm.hitpoints <= 0 then
harmer.experience = harmer.experience + calc_xp( unit_to_harm.__cfg.level )
else
unit_to_harm.experience = unit_to_harm.experience + harmer.__cfg.level
harmer.experience = harmer.experience + unit_to_harm.__cfg.level
end
end
if kill ~= false and unit_to_harm.hitpoints <= 0 then
wml_actions.kill { id = unit_to_harm.id, animate = toboolean( animate ), fire_event = fire_event }
end
if animate then
wesnoth.delay(delay)
end
if variable then
wesnoth.set_variable(string.format("%s[%d]", variable, index - 1), { harm_amount = damage })
end
-- both units may no longer be alive at this point, so double check
if experience ~= false and unit_to_harm and unit_to_harm.valid then
unit_to_harm:advance(toboolean(animate), fire_event ~= false)
end
if experience ~= false and harmer and harmer.valid then
harmer:advance(toboolean(animate), fire_event ~= false)
end
end
wml_actions.redraw {}
end
wesnoth.set_variable ( "this_unit" ) -- clearing this_unit
utils.end_var_scope("this_unit", this_unit)
end
function wml_actions.heal_unit(cfg)
wesnoth.heal_unit(cfg)
end
@ -1255,103 +733,6 @@ function wml_actions.add_ai_behavior(cfg)
}
end
function wml_actions.find_path(cfg)
local filter_unit = helper.get_child(cfg, "traveler") or helper.wml_error("[find_path] missing required [traveler] tag")
-- only the first unit matching
local unit = wesnoth.get_units(filter_unit)[1] or helper.wml_error("[find_path]'s filter didn't match any unit")
local filter_location = helper.get_child(cfg, "destination") or helper.wml_error( "[find_path] missing required [destination] tag" )
-- support for $this_unit
local this_unit = utils.start_var_scope("this_unit")
wesnoth.set_variable ( "this_unit" ) -- clearing this_unit
wesnoth.set_variable("this_unit", unit.__cfg) -- cfg field needed
local variable = cfg.variable or "path"
local ignore_units = false
local ignore_teleport = false
if cfg.check_zoc == false then --if we do not want to check the ZoCs, we must ignore units
ignore_units = true
end
if cfg.check_teleport == false then --if we do not want to check teleport, we must ignore it
ignore_teleport = true
end
local allow_multiple_turns = cfg.allow_multiple_turns
local viewing_side
if not cfg.check_visibility then viewing_side = 0 end -- if check_visiblity then shroud is taken in account
local locations = wesnoth.get_locations(filter_location) -- only the location with the lowest distance and lowest movement cost will match. If there will still be more than 1, only the 1st maching one.
local max_cost = nil
if not allow_multiple_turns then max_cost = unit.moves end --to avoid wrong calculation on already moved units
local current_distance, current_cost = math.huge, math.huge
local current_location = {}
local width,heigth,border = wesnoth.get_map_size() -- data for test below
for index, location in ipairs(locations) do
-- we test if location passed to pathfinder is invalid (border); if is, do nothing, do not return and continue the cycle
if location[1] == 0 or location[1] == ( width + 1 ) or location[2] == 0 or location[2] == ( heigth + 1 ) then
else
local distance = helper.distance_between ( unit.x, unit.y, location[1], location[2] )
-- if we pass an unreachable locations an high value will be returned
local path, cost = wesnoth.find_path( unit, location[1], location[2], { max_cost = max_cost, ignore_units = ignore_units, ignore_teleport = ignore_teleport, viewing_side = viewing_side } )
if ( distance < current_distance and cost <= current_cost ) or ( cost < current_cost and distance <= current_distance ) then -- to avoid changing the hex with one with less distance and more cost, or vice versa
current_distance = distance
current_cost = cost
current_location = location
end
end
end
if #current_location == 0 then wesnoth.message("WML warning","[find_path]'s filter didn't match any location")
else
local path, cost = wesnoth.find_path( unit, current_location[1], current_location[2], { max_cost = max_cost, ignore_units = ignore_units, ignore_teleport = ignore_teleport, viewing_side = viewing_side } )
local turns
if cost == 0 then -- if location is the same, of course it doesn't cost any MP
turns = 0
else
turns = math.ceil( ( ( cost - unit.moves ) / unit.max_moves ) + 1 )
end
if cost >= 42424242 then -- it's the high value returned for unwalkable or busy terrains
wesnoth.set_variable ( string.format("%s", variable), { hexes = 0 } ) -- set only length, nil all other values
-- support for $this_unit
wesnoth.set_variable ( "this_unit" ) -- clearing this_unit
utils.end_var_scope("this_unit", this_unit)
return end
if not allow_multiple_turns and turns > 1 then -- location cannot be reached in one turn
wesnoth.set_variable ( string.format("%s", variable), { hexes = 0 } )
-- support for $this_unit
wesnoth.set_variable ( "this_unit" ) -- clearing this_unit
utils.end_var_scope("this_unit", this_unit)
return end -- skip the cycles below
wesnoth.set_variable ( string.format( "%s", variable ), { hexes = current_distance, from_x = unit.x, from_y = unit.y, to_x = current_location[1], to_y = current_location[2], movement_cost = cost, required_turns = turns } )
for index, path_loc in ipairs(path) do
local sub_path, sub_cost = wesnoth.find_path( unit, path_loc[1], path_loc[2], { max_cost = max_cost, ignore_units = ignore_units, ignore_teleport = ignore_teleport, viewing_side = viewing_side } )
local sub_turns
if sub_cost == 0 then
sub_turns = 0
else
sub_turns = math.ceil( ( ( sub_cost - unit.moves ) / unit.max_moves ) + 1 )
end
wesnoth.set_variable ( string.format( "%s.step[%d]", variable, index - 1 ), { x = path_loc[1], y = path_loc[2], terrain = wesnoth.get_terrain( path_loc[1], path_loc[2] ), movement_cost = sub_cost, required_turns = sub_turns } ) -- this structure takes less space in the inspection window
end
end
-- support for $this_unit
wesnoth.set_variable ( "this_unit" ) -- clearing this_unit
utils.end_var_scope("this_unit", this_unit)
end
function wml_actions.store_starting_location(cfg)
local writer = utils.vwriter.init(cfg, "location")
for possibly_wrong_index, side in ipairs(wesnoth.get_sides(cfg)) do
@ -1459,98 +840,6 @@ function wml_actions.end_turn(cfg)
wesnoth.end_turn()
end
function wml_actions.endlevel(cfg)
local parsed = helper.parsed(cfg)
if wesnoth.check_end_level_disabled() then
wesnoth.message("Repeated [endlevel] execution, ignoring")
return
end
local next_scenario = cfg.next_scenario
if next_scenario then
wesnoth.set_next_scenario(next_scenario)
end
local end_text = cfg.end_text
local end_text_duration = cfg.end_text_duration
if end_text or end_text_duration then
wesnoth.set_end_campaign_text(end_text or "", end_text_duration)
end
local end_credits = cfg.end_credits
if end_credits ~= nil then
wesnoth.set_end_campaign_credits(end_credits)
end
local side_results = {}
for result in helper.child_range(parsed, "result") do
local side = result.side or helper.wml_error("[result] in [endlevel] missing required side= key")
side_results[side] = result
end
local there_is_a_human_victory = false
local there_is_a_human_defeat = false
local there_is_a_local_human_victory = false
local there_is_a_local_human_defeat = false
local bool_int = function(b)
if b == true then
return 1
elseif b == false then
return 0
else
return b
end
end
for k,v in ipairs(wesnoth.sides) do
local side_result = side_results[v.side] or {}
local victory_or_defeat = side_result.result or cfg.result or "victory"
local victory = victory_or_defeat == "victory"
if victory_or_defeat ~= "victory" and victory_or_defeat ~= "defeat" then
return helper.wml_error("invalid result= key in [endlevel] '" .. victory_or_defeat .."'")
end
if v.controller == "human" or v.controller == "network" then
if victory then
there_is_a_human_victory = true
else
there_is_a_human_defeat = true
end
end
if v.controller == "human" then
if victory then
there_is_a_local_human_victory = true
else
there_is_a_local_human_defeat = true
end
end
if side_result.bonus ~= nil then
v.carryover_bonus = bool_int(side_result.bonus)
elseif cfg.bonus ~= nil then
v.carryover_bonus = bool_int(cfg.bonus)
end
if side_result.carryover_add ~= nil then
v.carryover_add = side_result.carryover_add
elseif cfg.carryover_add ~= nil then
v.carryover_add = cfg.carryover_add
end
if side_result.carryover_percentage ~= nil then
v.carryover_percentage = side_result.carryover_percentage
elseif cfg.carryover_percentage ~= nil then
v.carryover_percentage = cfg.carryover_percentage
end
end
local proceed_to_next_level = there_is_a_human_victory or (not there_is_a_human_defeat and cfg.result ~= "defeat")
local victory = there_is_a_local_human_victory or (not there_is_a_local_human_defeat and proceed_to_next_level)
wesnoth.end_level {
music = cfg.music,
carryover_report = cfg.carryover_report,
save = cfg.save,
replay_save = cfg.replay_save,
linger_mode = cfg.linger_mode,
reveal_map = cfg.reveal_map,
proceed_to_next_level = proceed_to_next_level,
result = victory and "victory" or "defeat",
}
end
function wml_actions.event(cfg)
if cfg.remove then
wml_actions.remove_event(cfg)
@ -1661,79 +950,6 @@ function wml_actions.unsynced(cfg)
end)
end
wesnoth.wml_actions.random_placement = function(cfg)
local dist_le = nil
local parsed = helper.shallow_parsed(cfg)
-- TODO: In most cases this tag is used to place units, so maybe make include_borders=no the default for [filter_location]?
local filter = helper.get_child(parsed, "filter_location") or {}
local command = helper.get_child(parsed, "command") or helper.wml_error("[random_placement] missing required [command] subtag")
local distance = cfg.min_distance or 0
local num_items = cfg.num_items or helper.wml_error("[random_placement] missing required 'num_items' attribute")
local variable = cfg.variable or helper.wml_error("[random_placement] missing required 'variable' attribute")
local allow_less = cfg.allow_less == true
local variable_previous = utils.start_var_scope(variable)
if distance < 0 then
-- optimisation for distance = -1
dist_le = function() return false end
elseif distance == 0 then
-- optimisation for distance = 0
dist_le = function(x1,y1,x2,y2) return x1 == x2 and y1 == y2 end
else
-- optimisation: cloasure is faster than string lookups.
local math_abs = math.abs
-- same effect as helper.distance_between(x1,y1,x2,y2) <= distance but faster.
dist_le = function(x1,y1,x2,y2)
local d_x = math_abs(x1-x2)
if d_x > distance then
return false
end
if d_x % 2 ~= 0 then
if x1 % 2 == 0 then
y2 = y2 - 0.5
else
y2 = y2 + 0.5
end
end
local d_y = math_abs(y1-y2)
return d_x + 2*d_y <= 2*distance
end
end
local locs = wesnoth.get_locations(filter)
if type(num_items) == "string" then
num_items = math.floor(loadstring("local size = " .. #locs .. "; return " .. num_items)())
print("num_items=" .. num_items .. ", #locs=" .. #locs)
end
local size = #locs
for i = 1, num_items do
if size == 0 then
if allow_less then
print("placed only " .. i .. " items")
return
else
helper.wml_error("[random_placement] failed to place items. only " .. i .. " items were placed")
end
end
local index = wesnoth.random(size)
local point = locs[index]
wesnoth.set_variable(variable .. ".x", point[1])
wesnoth.set_variable(variable .. ".y", point[2])
wesnoth.set_variable(variable .. ".n", i)
for j = size, 1, -1 do
if dist_le(locs[j][1], locs[j][2], point[1], point[2]) then
-- optimisation: swapping elements and storing size in an extra variable is faster than table.remove(locs, j)
locs[j] = locs[size]
size = size - 1
end
end
wesnoth.wml_actions.command (command)
end
utils.end_var_scope(variable, variable_previous)
end
local function on_board(x, y)
if type(x) ~= "number" or type(y) ~= "number" then
return false
@ -1788,6 +1004,42 @@ wml_actions.teleport = function(cfg)
wesnoth.teleport(unit, cfg.check_passability == false, cfg.clear_shroud ~= false, cfg.animate)
end
function wml_actions.remove_sound_source(cfg)
wesnoth.remove_sound_source(cfg.id)
end
function wml_actions.sound_source(cfg)
wesnoth.add_sound_source(cfg)
end
function wml_actions.deprecated_message(cfg)
wesnoth.log('wml', cfg.message)
end
function wml_actions.wml_message(cfg)
local logger = cfg.logger or ''
wesnoth.log(cfg.logger, cfg.message, cfg.to_chat)
end
local function parse_fog_cfg(cfg)
-- Side filter
local ssf = helper.child(cfg, "filter_side")
local sides = wesnoth.get_sides(ssf or {})
-- Location filter
local locs = wesnoth.get_locations(cfg)
return locs, sides
end
function wml_actions.lift_fog(cfg)
local locs, sides = parse_fog_cfg(cfg)
wesnoth.remove_fog(sides, locs, not cfg.multiturn)
end
function wml_actions.reset_fog(cfg)
local locs, sides = parse_fog_cfg(cfg)
wesnoth.add_fog(sides, locs, cfg.reset_view)
end
function wml_actions.set_variable(cfg)
local name = cfg.name or helper.wml_error "trying to set a variable with an empty name"
local var = wesnoth.get_variable(name)
@ -1920,3 +1172,4 @@ function wml_actions.set_variable(cfg)
wesnoth.set_variable(name, table.concat(string_to_join, separator))
end
end
end

93
data/lua/wml/endlevel.lua Normal file
View file

@ -0,0 +1,93 @@
local helper = wesnoth.require "lua/helper.lua"
function wesnoth.wml_actions.endlevel(cfg)
local parsed = helper.parsed(cfg)
if wesnoth.check_end_level_disabled() then
wesnoth.message("Repeated [endlevel] execution, ignoring")
return
end
local next_scenario = cfg.next_scenario
if next_scenario then
wesnoth.set_next_scenario(next_scenario)
end
local end_text = cfg.end_text
local end_text_duration = cfg.end_text_duration
if end_text or end_text_duration then
wesnoth.set_end_campaign_text(end_text or "", end_text_duration)
end
local end_credits = cfg.end_credits
if end_credits ~= nil then
wesnoth.set_end_campaign_credits(end_credits)
end
local side_results = {}
for result in helper.child_range(parsed, "result") do
local side = result.side or helper.wml_error("[result] in [endlevel] missing required side= key")
side_results[side] = result
end
local there_is_a_human_victory = false
local there_is_a_human_defeat = false
local there_is_a_local_human_victory = false
local there_is_a_local_human_defeat = false
local bool_int = function(b)
if b == true then
return 1
elseif b == false then
return 0
else
return b
end
end
for k,v in ipairs(wesnoth.sides) do
local side_result = side_results[v.side] or {}
local victory_or_defeat = side_result.result or cfg.result or "victory"
local victory = victory_or_defeat == "victory"
if victory_or_defeat ~= "victory" and victory_or_defeat ~= "defeat" then
return helper.wml_error("invalid result= key in [endlevel] '" .. victory_or_defeat .."'")
end
if v.controller == "human" or v.controller == "network" then
if victory then
there_is_a_human_victory = true
else
there_is_a_human_defeat = true
end
end
if v.controller == "human" then
if victory then
there_is_a_local_human_victory = true
else
there_is_a_local_human_defeat = true
end
end
if side_result.bonus ~= nil then
v.carryover_bonus = bool_int(side_result.bonus)
elseif cfg.bonus ~= nil then
v.carryover_bonus = bool_int(cfg.bonus)
end
if side_result.carryover_add ~= nil then
v.carryover_add = side_result.carryover_add
elseif cfg.carryover_add ~= nil then
v.carryover_add = cfg.carryover_add
end
if side_result.carryover_percentage ~= nil then
v.carryover_percentage = side_result.carryover_percentage
elseif cfg.carryover_percentage ~= nil then
v.carryover_percentage = cfg.carryover_percentage
end
end
local proceed_to_next_level = there_is_a_human_victory or (not there_is_a_human_defeat and cfg.result ~= "defeat")
local victory = there_is_a_local_human_victory or (not there_is_a_local_human_defeat and proceed_to_next_level)
wesnoth.end_level {
music = cfg.music,
carryover_report = cfg.carryover_report,
save = cfg.save,
replay_save = cfg.replay_save,
linger_mode = cfg.linger_mode,
reveal_map = cfg.reveal_map,
proceed_to_next_level = proceed_to_next_level,
result = victory and "victory" or "defeat",
}
end

View file

@ -0,0 +1,99 @@
local helper = wesnoth.require "lua/helper.lua"
local utils = wesnoth.require "lua/wml-utils.lua"
function wesnoth.wml_actions.find_path(cfg)
local filter_unit = helper.get_child(cfg, "traveler") or helper.wml_error("[find_path] missing required [traveler] tag")
-- only the first unit matching
local unit = wesnoth.get_units(filter_unit)[1] or helper.wml_error("[find_path]'s filter didn't match any unit")
local filter_location = helper.get_child(cfg, "destination") or helper.wml_error( "[find_path] missing required [destination] tag" )
-- support for $this_unit
local this_unit = utils.start_var_scope("this_unit")
wesnoth.set_variable ( "this_unit" ) -- clearing this_unit
wesnoth.set_variable("this_unit", unit.__cfg) -- cfg field needed
local variable = cfg.variable or "path"
local ignore_units = false
local ignore_teleport = false
if cfg.check_zoc == false then --if we do not want to check the ZoCs, we must ignore units
ignore_units = true
end
if cfg.check_teleport == false then --if we do not want to check teleport, we must ignore it
ignore_teleport = true
end
local allow_multiple_turns = cfg.allow_multiple_turns
local viewing_side
if not cfg.check_visibility then viewing_side = 0 end -- if check_visiblity then shroud is taken in account
local locations = wesnoth.get_locations(filter_location) -- only the location with the lowest distance and lowest movement cost will match. If there will still be more than 1, only the 1st maching one.
local max_cost = nil
if not allow_multiple_turns then max_cost = unit.moves end --to avoid wrong calculation on already moved units
local current_distance, current_cost = math.huge, math.huge
local current_location = {}
local width,heigth,border = wesnoth.get_map_size() -- data for test below
for index, location in ipairs(locations) do
-- we test if location passed to pathfinder is invalid (border); if is, do nothing, do not return and continue the cycle
if location[1] == 0 or location[1] == ( width + 1 ) or location[2] == 0 or location[2] == ( heigth + 1 ) then
else
local distance = helper.distance_between ( unit.x, unit.y, location[1], location[2] )
-- if we pass an unreachable locations an high value will be returned
local path, cost = wesnoth.find_path( unit, location[1], location[2], { max_cost = max_cost, ignore_units = ignore_units, ignore_teleport = ignore_teleport, viewing_side = viewing_side } )
if ( distance < current_distance and cost <= current_cost ) or ( cost < current_cost and distance <= current_distance ) then -- to avoid changing the hex with one with less distance and more cost, or vice versa
current_distance = distance
current_cost = cost
current_location = location
end
end
end
if #current_location == 0 then wesnoth.message("WML warning","[find_path]'s filter didn't match any location")
else
local path, cost = wesnoth.find_path( unit, current_location[1], current_location[2], { max_cost = max_cost, ignore_units = ignore_units, ignore_teleport = ignore_teleport, viewing_side = viewing_side } )
local turns
if cost == 0 then -- if location is the same, of course it doesn't cost any MP
turns = 0
else
turns = math.ceil( ( ( cost - unit.moves ) / unit.max_moves ) + 1 )
end
if cost >= 42424242 then -- it's the high value returned for unwalkable or busy terrains
wesnoth.set_variable ( string.format("%s", variable), { hexes = 0 } ) -- set only length, nil all other values
-- support for $this_unit
wesnoth.set_variable ( "this_unit" ) -- clearing this_unit
utils.end_var_scope("this_unit", this_unit)
return end
if not allow_multiple_turns and turns > 1 then -- location cannot be reached in one turn
wesnoth.set_variable ( string.format("%s", variable), { hexes = 0 } )
-- support for $this_unit
wesnoth.set_variable ( "this_unit" ) -- clearing this_unit
utils.end_var_scope("this_unit", this_unit)
return end -- skip the cycles below
wesnoth.set_variable ( string.format( "%s", variable ), { hexes = current_distance, from_x = unit.x, from_y = unit.y, to_x = current_location[1], to_y = current_location[2], movement_cost = cost, required_turns = turns } )
for index, path_loc in ipairs(path) do
local sub_path, sub_cost = wesnoth.find_path( unit, path_loc[1], path_loc[2], { max_cost = max_cost, ignore_units = ignore_units, ignore_teleport = ignore_teleport, viewing_side = viewing_side } )
local sub_turns
if sub_cost == 0 then
sub_turns = 0
else
sub_turns = math.ceil( ( ( sub_cost - unit.moves ) / unit.max_moves ) + 1 )
end
wesnoth.set_variable ( string.format( "%s.step[%d]", variable, index - 1 ), { x = path_loc[1], y = path_loc[2], terrain = wesnoth.get_terrain( path_loc[1], path_loc[2] ), movement_cost = sub_cost, required_turns = sub_turns } ) -- this structure takes less space in the inspection window
end
end
-- support for $this_unit
wesnoth.set_variable ( "this_unit" ) -- clearing this_unit
utils.end_var_scope("this_unit", this_unit)
end

204
data/lua/wml/harm_unit.lua Normal file
View file

@ -0,0 +1,204 @@
local helper = wesnoth.require "lua/helper.lua"
local utils = wesnoth.require "lua/wml-utils.lua"
local wml_actions = wesnoth.wml_actions
function wml_actions.harm_unit(cfg)
local filter = helper.get_child(cfg, "filter") or helper.wml_error("[harm_unit] missing required [filter] tag")
-- we need to use shallow_literal field, to avoid raising an error if $this_unit (not yet assigned) is used
if not helper.shallow_literal(cfg).amount then helper.wml_error("[harm_unit] has missing required amount= attribute") end
local variable = cfg.variable -- kept out of the way to avoid problems
local _ = wesnoth.textdomain "wesnoth"
-- #textdomain wesnoth
local harmer
local function toboolean( value ) -- helper for animate fields
-- units will be animated upon leveling or killing, even
-- with special attacker and defender values
if value then return true
else return false end
end
local this_unit = utils.start_var_scope("this_unit")
for index, unit_to_harm in ipairs(wesnoth.get_units(filter)) do
if unit_to_harm.valid then
-- block to support $this_unit
wesnoth.set_variable ( "this_unit" ) -- clearing this_unit
wesnoth.set_variable("this_unit", unit_to_harm.__cfg) -- cfg field needed
local amount = tonumber(cfg.amount)
local animate = cfg.animate -- attacker and defender are special values
local delay = cfg.delay or 500
local kill = cfg.kill
local fire_event = cfg.fire_event
local primary_attack = helper.get_child(cfg, "primary_attack")
local secondary_attack = helper.get_child(cfg, "secondary_attack")
local harmer_filter = helper.get_child(cfg, "filter_second")
local experience = cfg.experience
local resistance_multiplier = tonumber(cfg.resistance_multiplier) or 1
if harmer_filter then harmer = wesnoth.get_units(harmer_filter)[1] end
-- end of block to support $this_unit
if animate then
if animate ~= "defender" and harmer and harmer.valid then
wesnoth.scroll_to_tile(harmer.x, harmer.y, true)
wml_actions.animate_unit {
flag = "attack",
hits = true,
with_bars = true,
T.filter { id = harmer.id },
T.primary_attack ( primary_attack ),
T.secondary_attack ( secondary_attack ),
T.facing { x = unit_to_harm.x, y = unit_to_harm.y },
}
end
wesnoth.scroll_to_tile(unit_to_harm.x, unit_to_harm.y, true)
end
-- the two functions below are taken straight from the C++ engine, utils.cpp and actions.cpp, with a few unuseful parts removed
-- may be moved in helper.lua in 1.11
local function round_damage( base_damage, bonus, divisor )
local rounding
if base_damage == 0 then return 0
else
if bonus < divisor or divisor == 1 then
rounding = divisor / 2 - 0
else
rounding = divisor / 2 - 1
end
return math.max( 1, math.floor( ( base_damage * bonus + rounding ) / divisor ) )
end
end
local function calculate_damage( base_damage, alignment, tod_bonus, resistance, modifier )
local damage_multiplier = 100
if alignment == "lawful" then
damage_multiplier = damage_multiplier + tod_bonus
elseif alignment == "chaotic" then
damage_multiplier = damage_multiplier - tod_bonus
elseif alignment == "liminal" then
damage_multiplier = damage_multiplier - math.abs( tod_bonus )
else -- neutral, do nothing
end
local resistance_modified = resistance * modifier
damage_multiplier = damage_multiplier * resistance_modified
local damage = round_damage( base_damage, damage_multiplier, 10000 ) -- if harmer.status.slowed, this may be 20000 ?
return damage
end
local damage = calculate_damage(
amount,
cfg.alignment or "neutral",
wesnoth.get_time_of_day( { unit_to_harm.x, unit_to_harm.y, true } ).lawful_bonus,
wesnoth.unit_resistance( unit_to_harm, cfg.damage_type or "dummy" ),
resistance_multiplier
)
if unit_to_harm.hitpoints <= damage then
if kill == false then damage = unit_to_harm.hitpoints - 1
else damage = unit_to_harm.hitpoints
end
end
unit_to_harm.hitpoints = unit_to_harm.hitpoints - damage
local text = string.format("%d%s", damage, "\n")
local add_tab = false
local gender = unit_to_harm.__cfg.gender
local function set_status(name, male_string, female_string, sound)
if not cfg[name] or unit_to_harm.status[name] then return end
if gender == "female" then
text = string.format("%s%s%s", text, tostring(female_string), "\n")
else
text = string.format("%s%s%s", text, tostring(male_string), "\n")
end
unit_to_harm.status[name] = true
add_tab = true
if animate and sound then -- for unhealable, that has no sound
wesnoth.play_sound (sound)
end
end
if not unit_to_harm.status.unpoisonable then
set_status("poisoned", _"poisoned", _"female^poisoned", "poison.ogg")
end
set_status("slowed", _"slowed", _"female^slowed", "slowed.wav")
set_status("petrified", _"petrified", _"female^petrified", "petrified.ogg")
set_status("unhealable", _"unhealable", _"female^unhealable")
-- Extract unit and put it back to update animation if status was changed
wesnoth.extract_unit(unit_to_harm)
wesnoth.put_unit(unit_to_harm)
if add_tab then
text = string.format("%s%s", "\t", text)
end
if animate and animate ~= "attacker" then
if harmer and harmer.valid then
wml_actions.animate_unit {
flag = "defend",
hits = true,
with_bars = true,
T.filter { id = unit_to_harm.id },
T.primary_attack ( primary_attack ),
T.secondary_attack ( secondary_attack ),
T.facing { x = harmer.x, y = harmer.y },
}
else
wml_actions.animate_unit {
flag = "defend",
hits = true,
with_bars = true,
T.filter { id = unit_to_harm.id },
T.primary_attack ( primary_attack ),
T.secondary_attack ( secondary_attack ),
}
end
end
wesnoth.float_label( unit_to_harm.x, unit_to_harm.y, string.format( "<span foreground='red'>%s</span>", text ) )
local function calc_xp( level ) -- to calculate the experience in case of kill
if level == 0 then return 4
else return level * 8 end
end
if experience ~= false and harmer and harmer.valid and wesnoth.is_enemy( unit_to_harm.side, harmer.side ) then -- no XP earned for harming friendly units
if kill ~= false and unit_to_harm.hitpoints <= 0 then
harmer.experience = harmer.experience + calc_xp( unit_to_harm.__cfg.level )
else
unit_to_harm.experience = unit_to_harm.experience + harmer.__cfg.level
harmer.experience = harmer.experience + unit_to_harm.__cfg.level
end
end
if kill ~= false and unit_to_harm.hitpoints <= 0 then
wml_actions.kill { id = unit_to_harm.id, animate = toboolean( animate ), fire_event = fire_event }
end
if animate then
wesnoth.delay(delay)
end
if variable then
wesnoth.set_variable(string.format("%s[%d]", variable, index - 1), { harm_amount = damage })
end
-- both units may no longer be alive at this point, so double check
if experience ~= false and unit_to_harm and unit_to_harm.valid then
unit_to_harm:advance(toboolean(animate), fire_event ~= false)
end
if experience ~= false and harmer and harmer.valid then
harmer:advance(toboolean(animate), fire_event ~= false)
end
end
wml_actions.redraw {}
end
wesnoth.set_variable ( "this_unit" ) -- clearing this_unit
utils.end_var_scope("this_unit", this_unit)
end

View file

@ -5,10 +5,7 @@ local location_set = wesnoth.require "lua/location_set.lua"
local _ = wesnoth.textdomain "wesnoth"
local function log(msg, level)
wesnoth.wml_actions.wml_message({
message = msg,
logger = level,
})
wesnoth.log(level, msg, true)
end
local function get_image(cfg, speaker)
@ -24,6 +21,10 @@ local function get_image(cfg, speaker)
image = speaker.portrait
end
if image == "none" or image == nil then
return "", true
end
if image:find("~RIGHT%(%)") then
left_side = false
-- The percent signs escape the parentheses for a literal match
@ -38,10 +39,6 @@ local function get_image(cfg, speaker)
image = image:gsub("~LEFT%(%)", "")
end
if image == "none" or image == nil then
return "", true
end
return image, left_side
end

View file

@ -0,0 +1,74 @@
local helper = wesnoth.require "lua/helper.lua"
local utils = wesnoth.require "lua/wml-utils.lua"
local wml_actions = wesnoth.wml_actions
function wml_actions.modify_unit(cfg)
local unit_variable = "LUA_modify_unit"
local function handle_attributes(cfg, unit_path, toplevel)
for current_key, current_value in pairs(helper.shallow_parsed(cfg)) do
if type(current_value) ~= "table" and (not toplevel or current_key ~= "type") then
wesnoth.set_variable(string.format("%s.%s", unit_path, current_key), current_value)
end
end
end
local function handle_child(cfg, unit_path)
local children_handled = {}
local cfg = helper.shallow_parsed(cfg)
handle_attributes(cfg, unit_path)
for current_index, current_table in ipairs(cfg) do
local current_tag = current_table[1]
local tag_index = children_handled[current_tag] or 0
handle_child(current_table[2], string.format("%s.%s[%u]",
unit_path, current_tag, tag_index))
children_handled[current_tag] = tag_index + 1
end
end
local filter = helper.get_child(cfg, "filter") or helper.wml_error "[modify_unit] missing required [filter] tag"
local function handle_unit(unit_num)
local children_handled = {}
local unit_path = string.format("%s[%u]", unit_variable, unit_num)
local this_unit = wesnoth.get_variable(unit_path)
wesnoth.set_variable("this_unit", this_unit)
handle_attributes(cfg, unit_path, true)
for current_index, current_table in ipairs(helper.shallow_parsed(cfg)) do
local current_tag = current_table[1]
if current_tag == "filter" then
-- nothing
elseif current_tag == "object" or current_tag == "trait" or current_tag == "advancement" then
local unit = wesnoth.get_variable(unit_path)
unit = wesnoth.create_unit(unit)
wesnoth.add_modification(unit, current_tag, current_table[2])
unit = unit.__cfg;
wesnoth.set_variable(unit_path, unit)
else
local tag_index = children_handled[current_tag] or 0
handle_child(current_table[2], string.format("%s.%s[%u]",
unit_path, current_tag, tag_index))
children_handled[current_tag] = tag_index + 1
end
end
if cfg.type then
if cfg.type ~= "" then wesnoth.set_variable(unit_path .. ".advances_to", cfg.type) end
wesnoth.set_variable(unit_path .. ".experience", wesnoth.get_variable(unit_path .. ".max_experience"))
end
wml_actions.kill({ id = this_unit.id, animate = false })
wml_actions.unstore_unit { variable = unit_path }
end
wml_actions.store_unit { {"filter", filter}, variable = unit_variable }
local max_index = wesnoth.get_variable(unit_variable .. ".length") - 1
local this_unit = utils.start_var_scope("this_unit")
for current_unit = 0, max_index do
handle_unit(current_unit)
end
utils.end_var_scope("this_unit", this_unit)
wesnoth.set_variable(unit_variable)
end

View file

@ -0,0 +1,75 @@
local helper = wesnoth.require "lua/helper.lua"
local utils = wesnoth.require "lua/wml-utils.lua"
wesnoth.wml_actions.random_placement = function(cfg)
local dist_le = nil
local parsed = helper.shallow_parsed(cfg)
-- TODO: In most cases this tag is used to place units, so maybe make include_borders=no the default for [filter_location]?
local filter = helper.get_child(parsed, "filter_location") or {}
local command = helper.get_child(parsed, "command") or helper.wml_error("[random_placement] missing required [command] subtag")
local distance = cfg.min_distance or 0
local num_items = cfg.num_items or helper.wml_error("[random_placement] missing required 'num_items' attribute")
local variable = cfg.variable or helper.wml_error("[random_placement] missing required 'variable' attribute")
local allow_less = cfg.allow_less == true
local variable_previous = utils.start_var_scope(variable)
if distance < 0 then
-- optimisation for distance = -1
dist_le = function() return false end
elseif distance == 0 then
-- optimisation for distance = 0
dist_le = function(x1,y1,x2,y2) return x1 == x2 and y1 == y2 end
else
-- optimisation: cloasure is faster than string lookups.
local math_abs = math.abs
-- same effect as helper.distance_between(x1,y1,x2,y2) <= distance but faster.
dist_le = function(x1,y1,x2,y2)
local d_x = math_abs(x1-x2)
if d_x > distance then
return false
end
if d_x % 2 ~= 0 then
if x1 % 2 == 0 then
y2 = y2 - 0.5
else
y2 = y2 + 0.5
end
end
local d_y = math_abs(y1-y2)
return d_x + 2*d_y <= 2*distance
end
end
local locs = wesnoth.get_locations(filter)
if type(num_items) == "string" then
num_items = math.floor(loadstring("local size = " .. #locs .. "; return " .. num_items)())
print("num_items=" .. num_items .. ", #locs=" .. #locs)
end
local size = #locs
for i = 1, num_items do
if size == 0 then
if allow_less then
print("placed only " .. i .. " items")
return
else
helper.wml_error("[random_placement] failed to place items. only " .. i .. " items were placed")
end
end
local index = wesnoth.random(size)
local point = locs[index]
wesnoth.set_variable(variable .. ".x", point[1])
wesnoth.set_variable(variable .. ".y", point[2])
wesnoth.set_variable(variable .. ".n", i)
for j = size, 1, -1 do
if dist_le(locs[j][1], locs[j][2], point[1], point[2]) then
-- optimisation: swapping elements and storing size in an extra variable is faster than table.remove(locs, j)
locs[j] = locs[size]
size = size - 1
end
end
wesnoth.wml_actions.command (command)
end
utils.end_var_scope(variable, variable_previous)
end

View file

@ -23,7 +23,7 @@ if(ENABLE_POT_UPDATE_TARGET)
COMMAND ${CMAKE_COMMAND}
-DPROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}"
-DMANPAGES="${ALL_MANPAGES}"
-P "${CMAKE_MODULE_PATH}/po4a-man.cmake"
-P "${CMAKE_SOURCE_DIR}/cmake/po4a-man.cmake"
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/wesnoth.6
${CMAKE_CURRENT_SOURCE_DIR}/wesnothd.6

View file

@ -83,7 +83,7 @@ if(ENABLE_POT_UPDATE_TARGET)
COMMAND ${CMAKE_COMMAND}
-DSOURCE="manual.${LINGUA}.xml"
-DCMD="${CMD}"
-P "${CMAKE_MODULE_PATH}/po4a-manual.cmake"
-P "${CMAKE_SOURCE_DIR}/cmake/po4a-manual.cmake"
COMMAND ${CMAKE_COMMAND} -E remove manual.${LINGUA}.xml
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/manual.${LINGUA}.xml
COMMENT "[update-po4a-manual ${LINGUA}] Building ${LINGUA}.html."

BIN
fonts/Lato-Bold.ttf Normal file

Binary file not shown.

BIN
fonts/Lato-Italic.ttf Normal file

Binary file not shown.

BIN
fonts/Lato-Regular.ttf Normal file

Binary file not shown.

94
fonts/OFL Executable file
View file

@ -0,0 +1,94 @@
Copyright (c) 2010-2015, Łukasz Dziedzic (dziedzic@typoland.com),
with Reserved Font Name Lato.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 B

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 B

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 B

After

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 B

After

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 B

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 B

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 231 B

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 B

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 B

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 B

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 B

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

View file

Before

Width:  |  Height:  |  Size: 126 B

After

Width:  |  Height:  |  Size: 126 B

View file

Before

Width:  |  Height:  |  Size: 216 B

After

Width:  |  Height:  |  Size: 216 B

View file

Before

Width:  |  Height:  |  Size: 119 B

After

Width:  |  Height:  |  Size: 119 B

View file

Before

Width:  |  Height:  |  Size: 212 B

After

Width:  |  Height:  |  Size: 212 B

View file

Before

Width:  |  Height:  |  Size: 132 B

After

Width:  |  Height:  |  Size: 132 B

View file

Before

Width:  |  Height:  |  Size: 123 B

After

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 381 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 626 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 446 B

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 366 B

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 408 B

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 570 B

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Some files were not shown because too many files have changed in this diff Show more