File: artifacts.lua

package info (click to toggle)
widelands 2%3A1.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 684,084 kB
  • sloc: cpp: 196,737; ansic: 19,395; python: 8,515; sh: 1,734; xml: 700; makefile: 46; lisp: 25
file content (216 lines) | stat: -rw-r--r-- 8,552 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
-- =======================================================================
--                         Artifact condition
-- =======================================================================

include "scripting/coroutine.lua" -- for sleep
include "scripting/win_conditions/win_condition_functions.lua"

push_textdomain("win_conditions")

include "scripting/win_conditions/win_condition_texts.lua"

local wc_name = "Artifacts"
-- This needs to be exactly like wc_name, but localized, because wc_name
-- will be used as the key to fetch the translation in C++
local wc_descname = _("Artifacts")
local wc_version = 1
local wc_desc = _("Search for ancient artifacts. Once all of them are found, the team who owns most of them will win the game.")
local wc_artifacts = "Artifacts owned"
-- This needs to be exactly like wc_artifacts, but localized, because wc_artifacts
-- will be used as the key to fetch the translation in C++
local wc_artifacts_i18n = _("Artifacts owned")

-- Table of all artifacts to conquer
local artifact_fields = {}

local r = {
   name = wc_name,
   description = wc_desc,
   peaceful_mode_allowed = true,
   map_tags = { "artifacts" }, -- Map tags needed so that this win condition will be available only for suitable maps
   init = function()
      -- Find all artifacts
      local map = wl.Game().map
      for x=0, map.width-1 do
         for y=0, map.height-1 do
            local field = map:get_field(x,y)
            if field.immovable and field.immovable:has_attribute("artifact") and field.immovable.fields[1] == field then
               table.insert(artifact_fields, map:get_field(x,y))
            end
         end
      end
   end,
   func = function()
      push_textdomain("win_conditions")
      -- set the objective with the game type for all players
      broadcast_objective("win_condition", wc_descname, wc_desc)

      local function _getkey(plr)
         if plr.team == 0 then
            -- Players without a team have team number 0. To distinguish between them, we use a special key.
            return "player" .. plr.number
         else
            return plr.team
         end
      end

      local artifacts_owner = {}
      local plrs = wl.Game().players

      -- statistic variables and functions
      -- initializing artifacts owned table
      local artifacts_per_player = {}
      -- funtion to calculate actual number of owned artifacts per player
      local function _calcowned()
         for idx, plr in ipairs(wl.Game().players) do
            artifacts_per_player[plr.number] = 0
         end
         for idx, plr in pairs(artifacts_owner) do
            artifacts_per_player[plr.number] = artifacts_per_player[plr.number] + 1
         end
      end

      if #artifact_fields == 0 then
         for idx, plr in ipairs(plrs) do
            send_to_inbox(plr, _("No Artifacts"), p(_("There are no artifacts on this map. This should not happen. Please file a bug report on %s and specify your Widelands version and the map you tried to load.")):bformat("https://www.widelands.org/wiki/ReportingBugs/"), {popup = true})
         end
         return
      end

      local found_artifact = {
         -- TRANSLATORS: Keep this as short as possible. You can also translate this as "New artifact"
         title = _("Artifact Found"),
         body_team = p(_([[Your team found a new artifact.]])),
         body_single = p(_([[You found a new artifact.]]))
      }
      local lost_artifact = {
         -- TRANSLATORS: Keep this as short as possible.
         title = _("Artifact Lost"),
         body_team = p(_([[One of your team’s artifacts was stolen by an enemy.]])),
         body_single = p(_([[One of your artifacts was stolen by an enemy.]]))
      }
      local stole_artifact = {
         -- TRANSLATORS: Keep this as short as possible.
         title = _("Artifact Conquered"),
         body_team = p(_([[Your team stole an artifact from an enemy.]])),
         body_single = p(_([[You stole an artifact from an enemy.]]))
      }

      local function _broadcast_to_team(player, msg, f)
         if player.team == 0 then
            player:send_to_inbox(msg.title, msg.body_single, {msg, field = f})
         else
            for idx, plr in ipairs(plrs) do
               if plr.team == player.team then
                  plr:send_to_inbox(msg.title, msg.body_team, {msg, field = f})
               end
            end
         end
      end


      -- Install statistics hook
      hooks.custom_statistic = {
         name = wc_artifacts,
         pic = "images/wui/stats/genstats_artifacts.png",
         calculator = function(p)
            _calcowned(p)
            return artifacts_per_player[p.number] or 0
         end,
      }

      -- Iterate all players, if one is defeated, remove him
      -- from the list, send him a defeated message and give him full vision
      -- Check if all artifacts have been found (i.e. controlled by a player)

      repeat
         sleep(1000)
         check_player_defeated(plrs, lost_game.title, lost_game.body, wc_descname, wc_version)
         local all_artifacts_found = true
         for idx, f in ipairs(artifact_fields) do
            if f.owner then
               if artifacts_owner[f] then
                  if f.owner.team ~= artifacts_owner[f].team or (f.owner.team == 0 and f.owner.number ~= artifacts_owner[f].number) then
                     -- a new team has this artifact
                     _broadcast_to_team(f.owner, stole_artifact, f)
                     _broadcast_to_team(artifacts_owner[f], lost_artifact, f)
                     artifacts_owner[f] = f.owner
                  end
               else
                  _broadcast_to_team(f.owner, found_artifact, f)
                  artifacts_owner[f] = f.owner
               end
            else
               all_artifacts_found = false
            end
         end
      until all_artifacts_found

      -- All artifacts are found, the game is over.
      local artifacts_per_team = {}
      for idx, plr in ipairs(wl.Game().players) do
         artifacts_per_team[_getkey(plr)] = 0
      end

      for idx, plr in pairs(artifacts_owner) do
         local key = _getkey(plr)
         artifacts_per_team[key] = artifacts_per_team[key] + 1
      end

      local function _max(a)
         local max = -1
         for k, v in pairs(a) do
            if v > max then max = v end
         end
         return max
      end

      local max_artifacts = _max(artifacts_per_team)

      local function _get_member_names(t)
         local membernames = {}
         for idx, plr in ipairs(t) do
            table.insert(membernames, plr.name)
         end
         return localize_list(membernames, ",")
      end

      local teams = {}
      local msg = h3(_("Overview:"))
      for idx, plr in ipairs(plrs) do
         if plr.team == 0 then
            local artifacts = (ngettext("%i artifact", "%i artifacts", artifacts_per_team[_getkey(plr)])):format(artifacts_per_team[_getkey(plr)])
            -- TRANSLATORS: e.g. Team 1 owns 5 artifacts.
            msg = msg .. p((_("%1$s owns %2$s.")):bformat(plr.name, artifacts))
         else
            if teams[plr.team] then
               teams[plr.team][#teams[plr.team]+1] = plr
            else
               teams[plr.team] = {plr}
            end
         end
      end
      for idx, t in ipairs(teams) do
         local members = _get_member_names(t)
         local artifacts = (ngettext("%i artifact", "%i artifacts", artifacts_per_team[_getkey(t[1])])):format(artifacts_per_team[_getkey(t[1])])
         -- TRANSLATORS: %1$i is the team's number; %2$s is a list of team members (e.g. "Steve, Robert, David"), %3$s is something like "x artifact(s)"
         msg = msg .. p((_("Team %1$i (%2$s) owns %3$s.")):bformat(t[1].team, members, artifacts))
      end

      for idx, plr in ipairs(plrs) do
         local key = _getkey(plr)
         -- If two or more teams have the same amount of artifacts, they are all considered winners.
         if artifacts_per_team[key] == max_artifacts then
            plr:send_to_inbox(won_game_over.title, won_game_over.body .. msg)
            wl.game.report_result(plr, 1, make_extra_data(plr, wc_descname, wc_version, {score=artifacts_per_team[key]}))
         else
            plr:send_to_inbox(lost_game_over.title, lost_game_over.body .. msg)
            wl.game.report_result(plr, 0, make_extra_data(plr, wc_descname, wc_version, {score=artifacts_per_team[key]}))
         end
      end

   pop_textdomain()
   end,
}
pop_textdomain()
return r