Showing
8 changed files
with
369 additions
and
15 deletions
... | ... | @@ -341,8 +341,16 @@ function _M:newGame() |
341 | 341 | if __module_extra_info.no_birth_popup then d.key:triggerVirtual("EXIT") end |
342 | 342 | end |
343 | 343 | |
344 | - if self.player.no_birth_levelup or __module_extra_info.no_birth_popup then birthend() | |
345 | - else self.player:playerLevelup(birthend, true) end | |
344 | + local birthend_lvlup = function() | |
345 | + if self.player.no_birth_levelup or __module_extra_info.no_birth_popup then birthend() | |
346 | + else self.player:playerLevelup(birthend, true) end | |
347 | + end | |
348 | + if self.player.custom_birthend then | |
349 | + self.player:custom_birthend(birth, birthend_lvlup) | |
350 | + self.player.custom_birthend = nil | |
351 | + else | |
352 | + birthend_lvlup() | |
353 | + end | |
346 | 354 | -- Player was loaded from a premade |
347 | 355 | else |
348 | 356 | self.calendar = Calendar.new("/data/calendar_"..(self.player.calendar or "allied")..".lua", "Today is the %s %s of the %s year of the Age of Ascendancy of Maj'Eyal.\nThe time is %02d:%02d.", 122, 167, 11) |
... | ... | @@ -376,7 +384,8 @@ function _M:newGame() |
376 | 384 | self:setTacticalMode(self.always_target) |
377 | 385 | self:triggerHook{"ToME:birthDone"} |
378 | 386 | end |
379 | - end, quickbirth, 800, 600) | |
387 | + end, quickbirth, math.min(math.max(game.w * 0.8, 800), 1200, game.w), 600) | |
388 | + -- end, quickbirth, 800, 600) | |
380 | 389 | self:registerDialog(birth) |
381 | 390 | end |
382 | 391 | ... | ... |
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | newBirthDescriptor{ |
21 | 21 | type = "class", |
22 | 22 | name = "Adventurer", |
23 | - locked = function() return profile.mod.allow_build.adventurer and true or "hide" end, | |
23 | + locked = function() return (profile.mod.allow_build.adventurer or profile.mod.allow_build.wanderer) and true or "hide" end, | |
24 | 24 | desc = { |
25 | 25 | _t"Adventurers can learn to do a bit of everything, getting training in whatever they happen to find.", |
26 | 26 | _t"#{bold}##GOLD#This is a bonus class for winning the game. It is by no means balanced.#WHITE##{normal}#", |
... | ... | @@ -31,6 +31,7 @@ newBirthDescriptor{ |
31 | 31 | { |
32 | 32 | __ALL__ = "disallow", |
33 | 33 | Adventurer = "allow", |
34 | + Wanderer = "allow", | |
34 | 35 | }, |
35 | 36 | }, |
36 | 37 | copy = { |
... | ... | @@ -63,7 +64,10 @@ newBirthDescriptor{ |
63 | 64 | if type(tt) == "function" then tt = tt(birth) end |
64 | 65 | |
65 | 66 | for t, _ in pairs(tt) do |
66 | - tts[t] = {false, 0} | |
67 | + local tt_def = birth.actor:getTalentTypeFrom(t) | |
68 | + if tt_def then | |
69 | + tts[t] = {false, 0} | |
70 | + end | |
67 | 71 | end |
68 | 72 | end |
69 | 73 | |
... | ... | @@ -73,7 +77,10 @@ newBirthDescriptor{ |
73 | 77 | |
74 | 78 | for t, v in pairs(tt) do |
75 | 79 | if profile.mod.allow_build[v[3]] then |
76 | - tts[t] = {false, 0} | |
80 | + local tt_def = birth.actor:getTalentTypeFrom(t) | |
81 | + if tt_def then | |
82 | + tts[t] = {false, 0} | |
83 | + end | |
77 | 84 | end |
78 | 85 | end |
79 | 86 | end |
... | ... | @@ -113,3 +120,91 @@ newBirthDescriptor{ |
113 | 120 | chooseCursedAuraTree = true, |
114 | 121 | }, |
115 | 122 | } |
123 | + | |
124 | +newBirthDescriptor{ | |
125 | + type = "subclass", | |
126 | + name = "Wanderer", | |
127 | + locked = function() return profile.mod.allow_build.wanderer and true or "hide" end, | |
128 | + desc = { | |
129 | + _t"Wanderers are adventurers who embrace the chaotic nature of the world. They start the game with the Combat Training talent tree, 3 random class trees and 1 random generic tree.", | |
130 | + _t"#{bold}##PURPLE#Every 5 levels they gain a new unlocked class tree, at random.#{normal}##LAST#", | |
131 | + _t"#{bold}##PURPLE#Every 10 levels starting at level 2 they gain a new unlocked generic tree, at random.#{normal}##LAST#", | |
132 | + _t"#{bold}##GOLD#This is a bonus class for the chaotically inclined. It is by no means balanced, fun or winnable, it is most of all #{italic}#RANDOM#{bold}#.#WHITE##{normal}#", | |
133 | + _t"Their most important stats depend on what they get to do.", | |
134 | + _t"#GOLD#Stat modifiers:", | |
135 | + _t"#LIGHT_BLUE# * +2 Strength, +2 Dexterity, +2 Constitution", | |
136 | + _t"#LIGHT_BLUE# * +2 Magic, +2 Willpower, +2 Cunning", | |
137 | + _t"#GOLD#Life per level:#LIGHT_BLUE# +2", | |
138 | + }, | |
139 | + not_on_random_boss = true, | |
140 | + stats = { str=2, con=2, dex=2, mag=2, wil=2, cun=2 }, | |
141 | + talents_types = function(birth) | |
142 | + return {["technique/combat-training"] = {true, 0}} | |
143 | + end, | |
144 | + copy_add = { | |
145 | + mana_regen = 0.5, | |
146 | + life_rating = 2, | |
147 | + unused_generics = 2, | |
148 | + unused_talents = 3, | |
149 | + unused_talents_types = 3, | |
150 | + }, | |
151 | + copy = { | |
152 | + custom_birthend = function(self, birth, finish) | |
153 | + game:registerDialog(require("mod.dialogs.WandererSeed").new(self, birth, finish)) | |
154 | + end, | |
155 | + randventurerLearn = function(self, what, silent) | |
156 | + local tt = table.remove(what == "class" and self.randventurer_class_trees or self.randventurer_generic_trees, 1) | |
157 | + if not tt then return end | |
158 | + local tt_def = self:getTalentTypeFrom(tt) | |
159 | + if tt_def then | |
160 | + if self:knowTalentType(tt) then return self:randventurerLearn(what, silent) end | |
161 | + if not silent then | |
162 | + local cat = tt_def.type:gsub("/.*", "") | |
163 | + local name = tstring{{"font", "bold"}, _t(cat, "talent category"):capitalize().." / "..tt_def.name:capitalize(), {"font", "normal"}} | |
164 | + game.bignews:say(90, "#GOLD#As you level up you learn the talent tree: #LIGHT_BLUE#%s", tostring(name)) | |
165 | + end | |
166 | + self:learnTalentType(tt) | |
167 | + end | |
168 | + end, | |
169 | + randventurer_last_learn_level = 0, | |
170 | + resolvers.register_callbacks{ callbackOnLevelup = function(self) | |
171 | + for i = self.randventurer_last_learn_level + 1, self.level do | |
172 | + if i % 5 == 0 then | |
173 | + self:randventurerLearn("class") | |
174 | + end | |
175 | + if i % 10 == 2 then | |
176 | + self:randventurerLearn("generic") | |
177 | + end | |
178 | + end | |
179 | + self.randventurer_last_learn_level = self.level | |
180 | + end }, | |
181 | + resolvers.inventorybirth{ id=true, transmo=true, | |
182 | + {type="weapon", subtype="dagger", name="iron dagger", autoreq=true, ego_chance=-1000}, | |
183 | + {type="weapon", subtype="dagger", name="iron dagger", autoreq=true, ego_chance=-1000}, | |
184 | + {type="weapon", subtype="longsword", name="iron longsword", ego_chance=-1000, ego_chance=-1000}, | |
185 | + {type="weapon", subtype="longsword", name="iron longsword", ego_chance=-1000, ego_chance=-1000}, | |
186 | + {type="weapon", subtype="greatsword", name="iron greatsword", autoreq=true, ego_chance=-1000, ego_chance=-1000}, | |
187 | + {type="weapon", subtype="staff", name="elm staff", autoreq=true, ego_chance=-1000}, | |
188 | + {type="weapon", subtype="mindstar", name="mossy mindstar", autoreq=true, ego_chance=-1000}, | |
189 | + {type="weapon", subtype="mindstar", name="mossy mindstar", autoreq=true, ego_chance=-1000}, | |
190 | + {type="armor", subtype="shield", name="iron shield", autoreq=true, ego_chance=-1000, ego_chance=-1000}, | |
191 | + {type="armor", subtype="shield", name="iron shield", autoreq=true, ego_chance=-1000, ego_chance=-1000}, | |
192 | + {type="armor", subtype="hands", name="iron gauntlets", autoreq=true, ego_chance=-1000, ego_chance=-1000}, | |
193 | + {type="armor", subtype="hands", name="rough leather gloves", ego_chance=-1000, ego_chance=-1000}, | |
194 | + {type="armor", subtype="light", name="rough leather armour", ego_chance=-1000, ego_chance=-1000}, | |
195 | + {type="armor", subtype="cloth", name="linen robe", autoreq=true, ego_chance=-1000}, | |
196 | + {type="scroll", subtype="rune", name="manasurge rune", ego_chance=-1000, ego_chance=-1000}, | |
197 | + {type="weapon", subtype="longbow", name="elm longbow", autoreq=true, ego_chance=-1000}, | |
198 | + {type="ammo", subtype="arrow", name="quiver of elm arrows", autoreq=true, ego_chance=-1000}, | |
199 | + {type="weapon", subtype="sling", name="rough leather sling", autoreq=true, ego_chance=-1000}, | |
200 | + {type="ammo", subtype="shot", name="pouch of iron shots", autoreq=true, ego_chance=-1000}, | |
201 | + {type="armor", subtype="cloak", name="linen cloak", autoreq=true, ego_chance=-1000}, | |
202 | + }, | |
203 | + chooseCursedAuraTree = true, | |
204 | + }, | |
205 | + cosmetic_options = { | |
206 | + wanderer_seed = { | |
207 | + {name=_t"Wanderer Seed", on_actor=function(actor) actor.alchemist_golem_is_drolem = true end, unlock="cosmetic_class_alchemist_drolem"}, | |
208 | + }, | |
209 | + }, | |
210 | +} | ... | ... |
... | ... | @@ -38,6 +38,24 @@ function Talents.aiLowerTacticals(tactical) |
38 | 38 | return tacts |
39 | 39 | end |
40 | 40 | |
41 | +local oldNewTalentType = Talents.newTalentType | |
42 | +Talents.newTalentType = function(self, t) | |
43 | + -- That's some trikery ... try to guess where the talent tree comes from, base game or addon | |
44 | + local i = 1 | |
45 | + while true do | |
46 | + local info = debug.getinfo(i, "S") | |
47 | + if not info then break end | |
48 | + if info.source then | |
49 | + local _, _, addon = info.source:find("/data%-([^/]+)/") | |
50 | + if addon then t.source = addon | |
51 | + elseif info.source:find("/data/talents") then t.source = "@vanilla@" | |
52 | + end | |
53 | + end | |
54 | + i = i + 1 | |
55 | + end | |
56 | + return oldNewTalentType(self, t) | |
57 | +end | |
58 | + | |
41 | 59 | local oldNewTalent = Talents.newTalent |
42 | 60 | Talents.newTalent = function(self, t) |
43 | 61 | local tt = engine.interface.ActorTalents.talents_types_def[t.type[1]] | ... | ... |
1 | +-- ToME - Tales of Maj'Eyal | |
2 | +-- Copyright (C) 2009 - 2019 Nicolas Casalini | |
3 | +-- | |
4 | +-- This program is free software: you can redistribute it and/or modify | |
5 | +-- it under the terms of the GNU General Public License as published by | |
6 | +-- the Free Software Foundation, either version 3 of the License, or | |
7 | +-- (at your option) any later version. | |
8 | +-- | |
9 | +-- This program is distributed in the hope that it will be useful, | |
10 | +-- but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | +-- GNU General Public License for more details. | |
13 | +-- | |
14 | +-- You should have received a copy of the GNU General Public License | |
15 | +-- along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | +-- | |
17 | +-- Nicolas Casalini "DarkGod" | |
18 | +-- darkgod@te4.org | |
19 | + | |
20 | +return _t"New Class: #LIGHT_GREEN#Wanderer", | |
21 | +_t[[You have wanderer quite a lot since your birth! | |
22 | +You can now create new characters with the #LIGHT_GREEN#Wanderer class#WHITE#. | |
23 | + | |
24 | +Wanderers start the game with 4 randomly selected talent trees points and gain new random ones as they levelup. | |
25 | +They are a #{bold}#bonus#{normal}# class, in no way meant to be balanced or even working with all possible talent combos. | |
26 | +Use at your own risk, and have fun.]] | ... | ... |
... | ... | @@ -90,7 +90,7 @@ function _M:init(title, actor, order, at_end, quickbirth, w, h) |
90 | 90 | self.c_ok = Button.new{text=_t" Play! ", fct=function() self:atEnd("created") end} |
91 | 91 | self.c_random = Button.new{text=_t"Random!", fct=function() self:randomBirth() end} |
92 | 92 | self.c_premade = Button.new{text=_t"Load premade", fct=function() self:loadPremadeUI() end} |
93 | - self.c_tile = Button.new{text=_t"Select custom tile", fct=function() self:selectTile() end} | |
93 | + self.c_tile = Button.new{text=_t"Custom tile", fct=function() self:selectTile() end} | |
94 | 94 | self.c_cancel = Button.new{text=_t"Cancel", fct=function() self:atEnd("quit") end} |
95 | 95 | self.c_tut = Button.new{text=_t"Tutorial", fct=function() self:tutorial() end} |
96 | 96 | self.c_options = Button.new{text=_t"Customize", fct=function() self:customizeOptions() end} |
... | ... | @@ -123,7 +123,9 @@ function _M:init(title, actor, order, at_end, quickbirth, w, h) |
123 | 123 | self.c_permadeath_text = Textzone.new{auto_width=true, auto_height=true, text=_t"Permadeath: "} |
124 | 124 | self.c_permadeath = Dropdown.new{width=150, fct=function(item) self:permadeathUse(item) end, on_select=function(item) self:updateDesc(item) end, list=self.all_permadeaths, nb_items=#self.all_permadeaths} |
125 | 125 | |
126 | - self.c_desc = TextzoneList.new{width=math.floor(self.iw / 3 - 10), height=self.ih - self.c_female.h - self.c_ok.h - self.c_difficulty.h - self.c_campaign.h - 10, scrollbar=true, pingpong=20, no_color_bleed=true} | |
126 | + local raceclass_w = math.min(262, math.floor(self.iw / 3 - 10)) | |
127 | + | |
128 | + self.c_desc = TextzoneList.new{width=self.iw - 2 * raceclass_w, height=self.ih - self.c_female.h - self.c_ok.h - self.c_difficulty.h - self.c_campaign.h - 10, scrollbar=true, pingpong=20, no_color_bleed=true} | |
127 | 129 | |
128 | 130 | self:setDescriptor("base", "base") |
129 | 131 | self:setDescriptor("world", self.default_campaign) |
... | ... | @@ -132,7 +134,7 @@ function _M:init(title, actor, order, at_end, quickbirth, w, h) |
132 | 134 | self:setDescriptor("sex", "Female") |
133 | 135 | |
134 | 136 | self:generateRaces() |
135 | - self.c_race = TreeList.new{width=math.floor(self.iw / 3 - 10), height=self.ih - self.c_female.h - self.c_ok.h - (self.c_extra_options.hide and 0 or self.c_extra_options.h) - self.c_difficulty.h - self.c_campaign.h - 10, scrollbar=true, columns={ | |
137 | + self.c_race = TreeList.new{width=raceclass_w, height=self.ih - self.c_female.h - self.c_ok.h - (self.c_extra_options.hide and 0 or self.c_extra_options.h) - self.c_difficulty.h - self.c_campaign.h - 10, scrollbar=true, columns={ | |
136 | 138 | {width=100, display_prop="name"}, |
137 | 139 | }, tree=self.all_races, |
138 | 140 | fct=function(item, sel, v) self:raceUse(item, sel, v) end, |
... | ... | @@ -141,7 +143,7 @@ function _M:init(title, actor, order, at_end, quickbirth, w, h) |
141 | 143 | } |
142 | 144 | |
143 | 145 | self:generateClasses() |
144 | - self.c_class = TreeList.new{width=math.floor(self.iw / 3 - 10), height=self.ih - self.c_female.h - self.c_ok.h - self.c_difficulty.h - self.c_campaign.h - 10, scrollbar=true, columns={ | |
146 | + self.c_class = TreeList.new{width=raceclass_w, height=self.ih - self.c_female.h - self.c_ok.h - self.c_difficulty.h - self.c_campaign.h - 10, scrollbar=true, columns={ | |
145 | 147 | {width=100, display_prop="name"}, |
146 | 148 | }, tree=self.all_classes, |
147 | 149 | fct=function(item, sel, v) self:classUse(item, sel, v) end, |
... | ... | @@ -393,10 +395,10 @@ function _M:makeDefault() |
393 | 395 | self:setDescriptor("permadeath", "Adventure") |
394 | 396 | self:setDescriptor("race", "Human") |
395 | 397 | self:setDescriptor("subrace", "Cornac") |
396 | - -- self:setDescriptor("class", "Mage") | |
397 | - -- self:setDescriptor("subclass", "Archmage") | |
398 | - self:setDescriptor("class", "Warrior") | |
399 | - self:setDescriptor("subclass", "Berserker") | |
398 | + self:setDescriptor("class", "Adventurer") | |
399 | + self:setDescriptor("subclass", "Wanderer") | |
400 | + -- self:setDescriptor("class", "Warrior") | |
401 | + -- self:setDescriptor("subclass", "Berserker") | |
400 | 402 | __module_extra_info.no_birth_popup = true |
401 | 403 | self:atEnd("created") |
402 | 404 | end | ... | ... |
... | ... | @@ -346,6 +346,17 @@ function _M:mouseLink(link, text, _, _, _, w, h, x, y) |
346 | 346 | }, true) |
347 | 347 | end |
348 | 348 | |
349 | +function _M:mouseClick(fct, text, _, _, _, w, h, x, y) | |
350 | + self:mouseZones({ | |
351 | + { x=x, y=y, w=w, h=h, fct=function(button) | |
352 | + game.tooltip_x, game.tooltip_y = 1, 1; game:tooltipDisplayAtMap(game.w, game.h, text) | |
353 | + if button == "left" then | |
354 | + fct() | |
355 | + end | |
356 | + end}, | |
357 | + }, true) | |
358 | +end | |
359 | + | |
349 | 360 | -- Switch between equipment sets (by reference only) for the equip doll |
350 | 361 | -- This makes sure the equipment shown in the equipdoll matches the tab setting |
351 | 362 | -- Done this way to make sure the actor's equipment is never actually touched |
... | ... | @@ -479,7 +490,8 @@ function _M:drawDialog(kind, actor_to_compare) |
479 | 490 | local text = "" |
480 | 491 | local dur_text = "" |
481 | 492 | |
482 | - if player.__te4_uuid and profile.auth and profile.auth.drupid and not config.settings.disable_all_connectivity and config.settings.tome.upload_charsheet then | |
493 | + -- if player.__te4_uuid and profile.auth and profile.auth.drupid and not config.settings.disable_all_connectivity and config.settings.tome.upload_charsheet then | |
494 | + if true then profile.auth.drupid=1 player.__te4_uuid="jklljkljlk" | |
483 | 495 | local path = "https://te4.org/characters/"..profile.auth.drupid.."/tome/"..player.__te4_uuid |
484 | 496 | local LinkTxt = ("Online URL: #LIGHT_BLUE##{underline}#%s#{normal}#"):tformat(path) |
485 | 497 | local Link_w, Link_h = self.font:size(LinkTxt) |
... | ... | @@ -612,6 +624,13 @@ function _M:drawDialog(kind, actor_to_compare) |
612 | 624 | local follow = (player.faction == "zigur" or player:attr("zigur_follower")) and _t"Zigur follower" or _t"Antimagic adherent" |
613 | 625 | self:mouseTooltip(self.TOOLTIP_ANTIMAGIC_USER, s:drawColorStringBlended(self.font, "#ORCHID#"..follow, w+200, h, 255, 255, 255, true)) |
614 | 626 | end |
627 | + | |
628 | + if player.randventurer_seed then | |
629 | + local text = ("- Seed: #LIGHT_STEEL_BLUE#%s"):tformat(player.randventurer_seed) | |
630 | + h = h + self.font_h | |
631 | + self:mouseClick(function() core.key.setClipboard(player.randventurer_seed) Dialog:simplePopup("Wanderer Seed", "Copied to clipboard!") end, _t"Click to copy to clipboard. You can share the wanderer seed with your friends, this way they can play with the same set of talents.", s:drawColorStringBlended(self.font, text, w, h, 255, 255, 255, true)) | |
632 | + end | |
633 | + | |
615 | 634 | h = h + self.font_h |
616 | 635 | s:drawStringBlended(self.font, _t"Size : "..(player:TextSizeCategory():capitalize()), w, h, 0, 200, 255, true) h = h + self.font_h |
617 | 636 | h = h + self.font_h | ... | ... |
game/modules/tome/dialogs/WandererSeed.lua
0 → 100644
1 | +-- ToME - Tales of Maj'Eyal | |
2 | +-- Copyright (C) 2009 - 2019 Nicolas Casalini | |
3 | +-- | |
4 | +-- This program is free software: you can redistribute it and/or modify | |
5 | +-- it under the terms of the GNU General Public License as published by | |
6 | +-- the Free Software Foundation, either version 3 of the License, or | |
7 | +-- (at your option) any later version. | |
8 | +-- | |
9 | +-- This program is distributed in the hope that it will be useful, | |
10 | +-- but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | +-- GNU General Public License for more details. | |
13 | +-- | |
14 | +-- You should have received a copy of the GNU General Public License | |
15 | +-- along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | +-- | |
17 | +-- Nicolas Casalini "DarkGod" | |
18 | +-- darkgod@te4.org | |
19 | + | |
20 | +require "engine.class" | |
21 | +local Dialog = require "engine.ui.Dialog" | |
22 | +local Separator = require "engine.ui.Separator" | |
23 | +local List = require "engine.ui.List" | |
24 | +local Button = require "engine.ui.Button" | |
25 | +local ButtonImage = require "engine.ui.ButtonImage" | |
26 | +local Textbox = require "engine.ui.Textbox" | |
27 | +local Textzone = require "engine.ui.Textzone" | |
28 | +local Checkbox = require "engine.ui.Checkbox" | |
29 | + | |
30 | +module(..., package.seeall, class.inherit(Dialog)) | |
31 | + | |
32 | +function _M:init(actor, birth, finish) | |
33 | + self.actor = actor | |
34 | + self.birth = birth | |
35 | + self.finish = finish | |
36 | + | |
37 | + Dialog.init(self, _t"Wanderer Options", 800, 300) | |
38 | + | |
39 | + local explain = Textzone.new{width=self.iw, auto_height=true, text=_t[[Welcome, wandering one! The Wanderer class uses a randomly selected set of talent trees. | |
40 | +You can now choose how this set is selected:]]} | |
41 | + local explain_random = Textzone.new{width=self.iw - 32, auto_height=true, text=_t[[Simply make a random set of trees, this is the default option. If you want to share it with friends, you will find the seed in the character's sheet later on.]]} | |
42 | + local explain_seed = Textzone.new{width=self.iw - 32, auto_height=true, text=_t[[If an other player gave you a seed to play, you can enter it here. Do note that while a seed will always work, you will only get the same talents set if you use the same DLC/addons.]]} | |
43 | + | |
44 | + local play = Button.new{text=_t"Play!", fct=function() game:unregisterDialog(self) self:makeWanderer() end} | |
45 | + local sep = Separator.new{dir="vertical", size=self.iw} | |
46 | + self.c_randomoption = Checkbox.new{title=_t"#{bold}##ANTIQUE_WHITE#Random#{normal}##LAST#", default=true, | |
47 | + on_change=function(c) if c then self:swapMode("random") else self.c_randomoption.checked = true end end, | |
48 | + } | |
49 | + self.c_seedoption = Checkbox.new{title=_t"#{bold}##ANTIQUE_WHITE#Seed#{normal}##LAST#", default=false, | |
50 | + on_change=function(c) if c then self:swapMode("seed") else self.c_seedoption.checked = true end end, | |
51 | + } | |
52 | + self.c_seed = Textbox.new{title=" "--[[do not translate]], text=__module_extra_info.tome_wanderer_seed or "", chars=40, max_len=200, fct=function() end, on_change=function(text) self:setSeed(text) end} | |
53 | + self:setSeed(__module_extra_info.tome_wanderer_seed) | |
54 | + | |
55 | + self:loadUI{ | |
56 | + {left=0, top=0, ui=explain}, | |
57 | + {left=0, top=explain, ui=sep}, | |
58 | + {left=0, top=sep, ui=self.c_randomoption}, | |
59 | + {left=32, top=self.c_randomoption, ui=explain_random}, | |
60 | + {left=0, top=explain_random, ui=self.c_seedoption}, | |
61 | + {left=self.c_seedoption, top=explain_random, ui=self.c_seed, hidden=true}, | |
62 | + {left=32, top=self.c_seedoption, ui=explain_seed}, | |
63 | + {hcenter=0, bottom=0, ui=play}, | |
64 | + } | |
65 | + self:setupUI(false, true) | |
66 | +end | |
67 | + | |
68 | +function _M:swapMode(mode) | |
69 | + if mode == "random" then | |
70 | + self.c_randomoption.checked = true | |
71 | + self.c_seedoption.checked = false | |
72 | + self:toggleDisplay(self.c_seed, false) | |
73 | + elseif mode == "seed" then | |
74 | + self.c_randomoption.checked = false | |
75 | + self.c_seedoption.checked = true | |
76 | + self:toggleDisplay(self.c_seed, true) | |
77 | + end | |
78 | + self.mode = mode | |
79 | +end | |
80 | + | |
81 | +function _M:setSeed(seed) | |
82 | + if not seed then return end | |
83 | + self.use_seed = seed | |
84 | +end | |
85 | + | |
86 | +function _M:makeWanderer() | |
87 | + local birth = self.birth | |
88 | + local actor = self.actor | |
89 | + local tts_class = {} | |
90 | + local tts_generic = {} | |
91 | + local tts_addons = {} | |
92 | + | |
93 | + -- Find all available trees | |
94 | + for _, class in ipairs(birth.all_classes) do if class.id ~= "Adventurer" then | |
95 | + for _, sclass in ipairs(class.nodes) do if sclass.def and ((not sclass.def.not_on_random_boss) or (sclass.id == "Stone Warden" and birth.descriptors_by_type.race == "Dwarf")) then | |
96 | + if birth.birth_descriptor_def.subclass[sclass.id].talents_types then | |
97 | + local tt = birth.birth_descriptor_def.subclass[sclass.id].talents_types | |
98 | + if type(tt) == "function" then tt = tt(birth) end | |
99 | + | |
100 | + for t, _ in pairs(tt) do | |
101 | + local tt_def = actor:getTalentTypeFrom(t) | |
102 | + if tt_def then | |
103 | + tts_addons[tt_def.source] = true | |
104 | + if tt_def.generic then | |
105 | + table.insert(tts_generic, t) | |
106 | + else | |
107 | + table.insert(tts_class, t) | |
108 | + end | |
109 | + end | |
110 | + end | |
111 | + end | |
112 | + | |
113 | + if birth.birth_descriptor_def.subclass[sclass.id].unlockable_talents_types then | |
114 | + local tt = birth.birth_descriptor_def.subclass[sclass.id].unlockable_talents_types | |
115 | + if type(tt) == "function" then tt = tt(birth) end | |
116 | + | |
117 | + for t, v in pairs(tt) do | |
118 | + if profile.mod.allow_build[v[3]] then | |
119 | + local tt_def = actor:getTalentTypeFrom(t) | |
120 | + if tt_def then | |
121 | + tts_addons[tt_def.source] = true | |
122 | + if tt_def.generic then | |
123 | + table.insert(tts_generic, t) | |
124 | + else | |
125 | + table.insert(tts_class, t) | |
126 | + end | |
127 | + end | |
128 | + end | |
129 | + end | |
130 | + end | |
131 | + end end | |
132 | + end end | |
133 | + actor.randventurer_class_trees = tts_class | |
134 | + actor.randventurer_generic_trees = tts_generic | |
135 | + | |
136 | + -- Compute the addons fingerprint | |
137 | + local md5 = require "md5" | |
138 | + tts_addons['@vanilla@'] = nil | |
139 | + actor.randventurer_addons = {game.__mod_info.version_string} | |
140 | + for a, _ in pairs(tts_addons) do | |
141 | + local addon = game.__mod_info and game.__mod_info.addons and game.__mod_info.addons[a] | |
142 | + if addon then | |
143 | + table.insert(actor.randventurer_addons, a.."-"..(addon.addon_version_txt or addon.version_txt or "???")) | |
144 | + else -- Shouldnt happen but heh | |
145 | + table.insert(actor.randventurer_addons, a) | |
146 | + end | |
147 | + end | |
148 | + -- Sort addons so that the fingerprint has meaning ;) | |
149 | + table.sort(actor.randventurer_addons) | |
150 | + local addons_md5 = mime.b64(md5.sum(table.concat(actor.randventurer_addons,'|'))) | |
151 | + actor.randventurer_fingerprint = addons_md5 | |
152 | + | |
153 | + -- Make the seed, or use the given one | |
154 | + local seed = rng.range(1, 99999999) | |
155 | + if self.mode == "seed" and self.use_seed then | |
156 | + local error = function() game:onTickEnd(function() require("engine.ui.Dialog"):simplePopup(_t"Wanderer Seed", _t"The wanderer seed you used was generated for a different set of DLC/addons. Your character will still work fine but you may not have the same talent set as the person that shared the seed with you.") end) end | |
157 | + local _, _, iseed, check = self.use_seed:find("^([0-9]+)%-(.*)$") | |
158 | + if not check or not tonumber(iseed) then | |
159 | + error() | |
160 | + else | |
161 | + seed = tonumber(iseed) | |
162 | + if check ~= addons_md5 then error() end | |
163 | + end | |
164 | + end | |
165 | + rng.seed(seed) | |
166 | + table.sort(actor.randventurer_class_trees) | |
167 | + table.sort(actor.randventurer_generic_trees) | |
168 | + table.shuffle(actor.randventurer_class_trees) | |
169 | + table.shuffle(actor.randventurer_generic_trees) | |
170 | + | |
171 | + actor.randventurer_seed = seed.."-"..addons_md5 | |
172 | + | |
173 | + rng.seed(os.time()) | |
174 | + | |
175 | + -- Give the starting trees | |
176 | + actor:randventurerLearn("class", true) | |
177 | + actor:randventurerLearn("class", true) | |
178 | + actor:randventurerLearn("class", true) | |
179 | + actor:randventurerLearn("generic", true) | |
180 | + | |
181 | + self.finish() | |
182 | +end | ... | ... |
-
Please register or login to post a comment