├── README.md
├── npc.png
├── desc1.png
├── desc2.png
├── desc3.png
├── desc4.png
├── ConvLib.aslx
├── compass.png
├── devtools.png
├── CombatLib.zip
├── notepad_xml.png
├── DanskConvLib.aslx
├── saveloadatts.png
├── enhanced_compass.png
├── notepad_context.png
├── type_attributes.png
├── empire
├── readme.md
├── lib.xml
├── interface.xml
└── Empire.aslx
├── compare.rb
├── ShipwiseLib.aslx
├── group_project.aslx
├── notes
└── italian.md
├── WeatherLib.aslx
├── braces.html
├── group_project_library.aslx
├── YamlToQuest.rb
├── QuestLib.aslx
├── LiquidLib.aslx
├── LiquidDemo.aslx
├── StackLibrary.aslx
├── ShopLib.aslx
├── InvPane2.aslx
├── StackLib.aslx
├── LockDemo.aslx
├── weather.aslx
├── LiftLib.aslx
├── EnhancedIt.aslx
├── third_past.aslx
├── StackDemo.aslx
├── ClockLib.aslx
├── CompliantNpcLib.aslx
└── SaveLoad.aslx
/README.md:
--------------------------------------------------------------------------------
1 | # quest
2 | Tutorials and Libraries for quest 5
3 |
--------------------------------------------------------------------------------
/npc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/npc.png
--------------------------------------------------------------------------------
/desc1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/desc1.png
--------------------------------------------------------------------------------
/desc2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/desc2.png
--------------------------------------------------------------------------------
/desc3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/desc3.png
--------------------------------------------------------------------------------
/desc4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/desc4.png
--------------------------------------------------------------------------------
/ConvLib.aslx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/ConvLib.aslx
--------------------------------------------------------------------------------
/compass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/compass.png
--------------------------------------------------------------------------------
/devtools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/devtools.png
--------------------------------------------------------------------------------
/CombatLib.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/CombatLib.zip
--------------------------------------------------------------------------------
/notepad_xml.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/notepad_xml.png
--------------------------------------------------------------------------------
/DanskConvLib.aslx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/DanskConvLib.aslx
--------------------------------------------------------------------------------
/saveloadatts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/saveloadatts.png
--------------------------------------------------------------------------------
/enhanced_compass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/enhanced_compass.png
--------------------------------------------------------------------------------
/notepad_context.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/notepad_context.png
--------------------------------------------------------------------------------
/type_attributes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThePix/quest/HEAD/type_attributes.png
--------------------------------------------------------------------------------
/empire/readme.md:
--------------------------------------------------------------------------------
1 | These three files are the start of a 4X game for Quest. I am not sure Quest is the best medium for this, and I have no plans to take these any further, but the files are there for anyone interested. Feel free to use this however you want.
2 |
3 | The Pixie, May/2018
4 |
--------------------------------------------------------------------------------
/compare.rb:
--------------------------------------------------------------------------------
1 | require "rexml/document"
2 | include REXML
3 |
4 |
5 |
6 |
7 |
8 |
9 | def get_lists filename
10 | doc = REXML::Document.new File.new(filename)
11 | templates = []
12 | doc.elements.each("library/template") do |temp|
13 | templates << temp.attributes["name"]
14 | end
15 | dynamic_templates = []
16 | doc.elements.each("library/dynamictemplate") do |temp|
17 | dynamic_templates << temp.attributes["name"]
18 | end
19 | verb_templates = []
20 | doc.elements.each("library/verbtemplate") do |temp|
21 | verb_templates << temp.attributes["name"]
22 | end
23 | return templates, dynamic_templates, verb_templates
24 | end
25 |
26 |
27 |
28 | a1, b1, c1 = get_lists "English.aslx"
29 | a2, b2, c2 = get_lists "Greek.aslx"
30 | p (a1 - a2)
31 | p (b1 - b2)
32 | p (c1 - c2)
33 |
--------------------------------------------------------------------------------
/ShipwiseLib.aslx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
17 |
18 | forward
19 | port
20 | starboard
21 | aft
22 | f
23 | p
24 | s
25 | a
26 | forward|port|starboard|aft|f|p|a|s|in|out|up|down|o|u|d)$]]>
27 |
28 |
--------------------------------------------------------------------------------
/group_project.aslx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | c76a1ed4-9935-44c1-97e7-b7857e268d49
8 | 1.0
9 | 2017
10 | false
11 | All rooms, objects, exits (if you name them), commands (if you name them) and functions you add to the game must have a name that starts with your initials (or other two letter identifier), and that includes the new name for gateway. This is to ensure there are no conflicts. If two people have a room called gateway in their zone, we will have problems when we put it together.
Commands and verb elements will generally be better submitted to the library. Functions might too if others will use them.
Use the Combined function to test in game if this is the final version or just your bit.
if (IsCombined()) msg("This is the full version!")
NOTE: Any changes you make to game, hub, or player will be lost (as well as any objects or commands or exits inside them) when you game is combined with everything else.
NOTE: The library may be updated periodically, and that may well affect the hub and player, but should not affect your zone.]]>
12 |
13 | StartScript
14 |
15 | false
16 |
17 |
50 |
51 |
52 |
53 | false
54 |
55 |
56 | AddToHubGateway (this)
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/notes/italian.md:
--------------------------------------------------------------------------------
1 | A list of translations needed for the Italian version of Quest
2 | -------------------------------------------------------------
3 |
4 | To support the AGAIN command, the command and abbreviation, plus an error message:
5 |
6 | again
7 | g
8 | There is nothing to repeat.
9 |
10 | This is used in the status panel; not sure why it is missing, it has been in Quest for years:
11 |
12 | Status
13 | Score
14 | Health
15 | Money
16 |
17 | Text for the interface:
18 |
19 | Type here...
20 | Continue...
21 |
22 | Various error messages for when the player uses ALL.
23 |
24 |
25 | Nothing here to take.
26 | You've nothing to drop.
27 | You've nothing to wear.
28 | You've nothing to take off.
29 |
30 | Possessives (the last three are netrual, male, female; all the same in English):
31 |
32 | its
33 | his
34 | her
35 | your
36 | their
37 | their
38 | their
39 |
40 | For a list when there is nothing there:
41 |
42 | nothing
43 |
44 | When the player locks a container:
45 |
46 | Locked.
47 |
48 | When saying who the author is:
49 |
50 | by
51 |
52 | Also:
53 |
54 | Eat
55 | Yes
56 | No
57 |
58 |
59 | Various messages for clothing (object.article will be "it" or "them" in English):
60 |
61 | "You put " + object.article + " on."
62 | "You can't wear " + object.article + "."
63 | "You would need to get " + object.article + " before you can put " + object.article + " on."
64 | "You would need to get " + object.article + " before you can take " + object.article + " off."
65 | "You are already wearing " + object.article + "."
66 | "You are not wearing " + object.article + "."
67 | "You cannot remove " + object.article + "!"
68 | "You cannot wear that over " + GetDisplayGarment(object) + "."
69 | "You cannot wear that while wearing " + GetDisplayGarment(object) + "."
70 | "You take " + object.article + " off."
71 | "You can't remove that while wearing " + GetDisplayGarment(object) + "."
72 |
73 | And for containers:
74 |
75 | "You can't put " + object.article + " there."
76 |
77 | This is added to an item when it is listed (eg "hat (worn)")
78 |
79 | worn
80 |
81 | Also these used for display verbs (when you click on an object, these are shown and can be clicked):
82 |
83 | Wear
84 | Remove
85 |
86 | Commands are tricky because we need to cover all possibilities, so please list any alternatives you can think of in the format "take #object# off".
87 |
88 | wear #object#
89 | remove #object#
90 | give #object#
91 | tell #object1# to #object2#
92 |
93 |
94 | These error responses are also a bit more tricky as they vary depending on the object. The WriteVerb function modifies the verb, so in the first, it might return "They are". This will work in Italian too.
95 |
96 | WriteVerb(object, "be") + " too heavy to be taken."
97 | "You can't carry any more items."
98 | "You can't put more items in " + object.article + "."
99 |
100 | "You can't put " + object.article + " there."
101 | "You can't give " + object.article + "."
102 | "You eat " + object.article + "."
103 | "It is too dark to make anything out."
104 | WriteVerb(object, "do") + " nothing."
105 |
106 |
107 |
--------------------------------------------------------------------------------
/WeatherLib.aslx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
18 |
19 | if (not HasInt(game, "weathercount")) {
20 | game.weathercount = 0
21 | }
22 | if (game.currentweather = null) {
23 | game.currentweather = PickOneObject(FilterByType(AllObjects(), "weather_type"))
24 | }
25 | game.weathercount = game.weathercount + 1
26 | do (game.currentweather, "weatherchangescript")
27 | if (game.weathertochange) {
28 | game.weathercount = 0
29 | exit = PickOneUnlockedExit(game.currentweather)
30 | game.currentweather = exit.to
31 | if (HasString(exit, "message") and not GetBoolean(game.pov.parent, "inside")) {
32 | msg (exit.message)
33 | }
34 | }
35 | if (not HasInt(game.pov, "soaking")) game.pov.soaking = 0
36 | if (not GetBoolean(game.pov.parent, "inside")) {
37 | game.pov.soaking = game.pov.soaking + game.currentweather.rain
38 | }
39 | else {
40 | game.pov.soaking = game.pov.soaking - 5
41 | }
42 | if (game.pov.soaking > 100) game.pov.soaking = 100
43 | if (0 > game.pov.soaking) game.pov.soaking = 0
44 |
45 |
46 |
47 |
48 | if (not GetBoolean(game.pov.parent, "inside")) {
49 | msg ("" + game.currentweather.alias)
50 | }
51 |
52 |
53 |
54 | return (game.currentweather.look)
55 |
56 |
57 |
58 | 0
59 |
60 | game.weathertochange = RandomChance(game.weathercount)
61 |
62 |
63 |
64 |
65 |
66 |
67 | _ObjectEditor
68 |
86 | The text processor in Quest allows you to create some complex strings, but if you miss a curly brace, it can lead to some weird errors that are difficult to spot. Paste your code into this box to have it check that you have as many start braces as end braces. If there is an error, the output will have properly formatted sections replaced by ---, which might help you find the error.
87 |
88 |
89 | As well as curly braces, it will also try to match parentheses and angle brackets.
90 |
91 |
92 | I have designed this with text output in mind, but it will probably work on Quest code too, and you should be able paste a whole script in. The text will be broken up into chunks at each msg (if you have "msg" in your text, you may have problems!). It will only find one error per bracket type per chunk.
93 |
94 |
95 | It is not that clever and some things will confuse it. For example, if you use greater than or less than in a text processor "if" directive, it will think that is an angle bracket and complain it is not matched. You could delete the offending greater than or less than symbols after pasting into this page to get around that.
96 |
Welcome to Star Empire. Click on the words to the right to navigate to different areas. Clicking "Home" will take you to the throne room, while clicking "Back" will take you back one level. Clicking "Next" to end this turn. Time will pass, and your empire will flourish or fail according to your instructions.
37 |
Click on an object in the lists on the right to see what actions you can perform with them.
38 |
Sorry, no hints yet.
39 |
Created by The Pixie.
Thanks to Alex Warren for creating Quest.
40 |
41 |
70 | ]]>
71 |
72 |
73 |
74 |
94 |
95 |
96 |
97 |
98 |
99 | help
100 |
103 |
104 |
105 |
106 |
107 | home
108 |
111 |
112 |
113 |
114 | planets
115 |
118 |
119 |
120 |
121 | research
122 |
125 |
126 |
127 |
128 | design
129 |
132 |
133 |
134 |
135 | military
136 |
139 |
140 |
141 |
142 |
143 | back
144 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 | .noselect {
160 | -webkit-touch-callout: none;
161 | -webkit-user-select: none;
162 | -khtml-user-select: none;
163 | -moz-user-select: none;
164 | -ms-user-select: none;
165 | user-select: none;
166 | }
167 |
168 |
169 | function ArrowClick(s) {
170 | ASLEvent("ArrowCallback", s);
171 | }
172 | function StarClick(s) {
173 | ASLEvent("StarCallback", s);
174 | }
175 |
176 |
177 |
178 |
179 |
180 | "
217 | JS.eval ("$('#gamePanel').css('display', 'block');")
218 | JS.eval ("$('#gamePanel').html('" + s +"');")
219 | // Need to do this here as the css method only changes the existing elements
220 | JS.eval ("$('.noselect').css('-webkit-touch-callout', 'none')")
221 | JS.eval ("$('.noselect').css('-webkit-user-select', 'none')")
222 | JS.eval ("$('.noselect').css('-khtml-user-select', 'none')")
223 | JS.eval ("$('.noselect').css('-moz-user-select', 'none')")
224 | JS.eval ("$('.noselect').css('ms-user-select', 'none')")
225 | JS.eval ("$('.noselect').css('user-select', 'none')")
226 | ]]>
227 |
228 |
229 | if (s = "0") {
230 | game.y = game.y + 20
231 | }
232 | if (s = "1") {
233 | game.x = game.x - 20
234 | }
235 | if (s = "2") {
236 | game.y = game.y - 20
237 | }
238 | if (s = "3") {
239 | game.x = game.x + 20
240 | }
241 | if (s = "4") {
242 | game.x = 300
243 | game.y = 200
244 | }
245 | if (s = "5") {
246 | game.scale = game.scale * 2
247 | }
248 | if (s = "6") {
249 | if (game.scale > 1) {
250 | game.scale = game.scale / 2
251 | }
252 | }
253 | Map
254 |
255 |
256 |
257 | foreach (o, GetDirectChildren(maproom)) {
258 | if (not o = player) {
259 | if (o.id = ToInt(s)) {
260 | do(o, "look")
261 | }
262 | }
263 | }
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
--------------------------------------------------------------------------------
/empire/Empire.aslx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 6b536464-42df-422b-8a83-bc2ca1397e85
9 | 0.0
10 | 2016
11 | Can you rule the galaxy?
12 | The Pixie
13 | Sci-Fi
14 |
15 | 900
16 |
17 | false
18 | false
19 | false
20 | false
21 | false
22 | Dosis
23 | 1
24 | 300
25 | 200
26 |
27 | false
28 |
29 | player.time = 1
30 | player.credits = 500
31 |
32 |
33 |
34 |
35 |
36 |
37 | Throne Room
38 | false
39 |
40 | request (SetInterfaceString, "PlacesObjectsLabel=News")
41 | JS.eval ("$('#page1').html('The throne room is the hub of your command centre, giving an overview of your empire.');")
42 |
43 | Welcome to your empire. It is not much, but you control one planet, with a basic mine, and a fleet of five ship Cobra ships.")
45 | msg ("This is just a \"proof of concept\" and there is not much you can do yet. If you research \"Fields\" you will soon discover photon torpedoes, but there is nothing else to discover yet. Do take a look at the star map though!")
46 | GenerateGalaxy (20)
47 | msg ("It is 237 years since the collapse. After two centuries of just struggling to live, the survivors on your planet are starting to look to the future. Old technology has been recovered from the ruins of the ancient cities, and five \"Cobra\" class warships have been built, and currently orbit the planet.")
48 | msg ("Are you ready to seize the memoment? To lead your people to the stars, to forge a new empire?")
49 | ]]>
50 |
51 | ClearScreen
52 |
53 |
54 |
55 |
56 | 0
57 |
58 |
59 | JS.eval ("$('#clock').html('" + this.time + "');")
60 |
61 |
62 | JS.eval ("$('#cash').html('" + this.credits + "');")
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | War Room
81 | false
82 |
83 | request (SetInterfaceString, "PlacesObjectsLabel=Fleets")
84 | JS.eval ("$('#page1').html('Organise and deploy your fleets.');")
85 |
86 |
87 | ClearScreen
88 |
89 |
90 |
91 |
92 | Look at
93 |
94 | Fleet 1
95 | " + this.alias + ""
97 | foreach (o, GetDirectChildren(this)) {
98 | s = s + " " + o.design.alias + ": " + o.number
99 | }
100 | msg (s)
101 | ]]>
102 |
103 |
104 | 5
105 | design1
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | Research Labs
115 | false
116 |
117 | request (SetInterfaceString, "PlacesObjectsLabel=Research areas")
118 | JS.eval ("$('#page1').html('Decide how much of your resources you will spend on each field of science. Each turn will bring you nearer to new discoveries.');")
119 |
120 |
121 | ClearScreen
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 | Fields
130 | This area of science is to do with fields, principally electromagnetic fields and gravity fields. Research in this direction may lead to artificial gravity, gravity bombs, anti-gravity and photon torpedeos.
131 |
132 |
133 |
134 | The photon torpedo is an unguided missile contructed of "hard" light.
135 | false
136 |
137 | Photon Torpedo
138 | Secondary weapon
139 |
140 |
141 |
142 |
143 | Basic laser
144 |
145 | Primary weapon
146 |
147 |
148 |
149 |
150 |
151 |
152 | Particle physics
153 | Research in construction will allow bigger ships and buildings to be constructed.
154 |
155 |
156 |
157 |
158 | Construction
159 |
160 |
161 |
162 |
163 | Vessel
164 | 1
165 | 100
166 | Caravel
167 |
168 |
169 |
170 |
171 |
172 | Basic mine
173 | 70
174 |
175 | 1
176 | Building
177 | 25
178 | Used to extract metals and other materials from the planet.
179 |
180 |
181 |
182 |
183 |
184 | Spacedock
185 |
186 | 1
187 | Building
188 | -10
189 | Used to extract metals and other materials from the planet.
190 | 200
191 |
192 |
193 |
194 |
195 |
196 |
197 | Design Office
198 | false
199 |
200 | request (SetInterfaceString, "PlacesObjectsLabel=Designs")
201 | JS.eval ("$('#page1').html('Here you can design ships for your fleet, using the technologies you have uncovered.');")
202 |
203 |
204 | ClearScreen
205 |
206 |
207 |
208 | Cobra
209 |
210 | Look at
211 |
212 | basiclaser
213 | caravel
214 | Name: " + this.alias)
216 | msg ("Body: " + this.vessel.alias)
217 | foreach (s, Split("Primary weapon;Secondary weapon;Turret;FTL engine;Sub-light engine;Sensor;Cloak;Other", ";")) {
218 | s2 = Replace(LCase(s), " ", "_")
219 | if (HasObject(this, s2)) {
220 | o = GetAttribute(this, s2)
221 | msg ("" + s + ": " + o.alias)
222 | }
223 | }
224 | ]]>
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 | false
234 |
235 | request (SetInterfaceString, "PlacesObjectsLabel=Star systems")
236 | Map
237 | JS.eval ("$('#page1').html('Use the map to explore the galaxy. Click the side arrows to scroll, the + and - to zoom in and out and the square to centre the view.');")
238 |
239 |
240 | JS.eval ("$('#gamePanel').css('display', 'none');")
241 |
242 |
243 | ClearScreen
244 |
245 |
246 |
247 |
248 | Home world
249 | 0
250 | 0
251 | red
252 | 0
253 |
254 | This is your home world; it has a pleasant atmosphere and a varied geography. An ideal base for your empire.
255 |
256 |
257 |
258 | 1
259 | Command Centre
260 | commandcentre
261 |
262 |
263 |
264 |
265 | 1
266 | Basic Mine (1)
267 |
268 | Look at
269 | Construct
270 | Condemn
271 |
272 | basicmine
273 |
274 |
275 |
276 |
277 | 1
278 | Basic dock (1)
279 | basicdockyard
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 | Command Centre
292 |
293 | 1
294 | Building
295 | 0
296 | It is from here that you control your empire. You can only have one, and if you ever lose it, you have lost the game.
297 |
298 |
299 |
--------------------------------------------------------------------------------
/ClockLib.aslx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
35 |
36 |
37 |
38 |
39 |
40 | 0
41 | 0
42 | 0
43 | 0
44 | 1
45 | 15
46 | 12 midnight
47 | 12 noon
48 | am
49 | pm
50 | false
51 | You take your fob watch from your pocket, and look at it. It's ###.
52 | You wait ### minutes, but nothing happens.
53 |
54 | JS.eval("$('#clock').html('" + TimeAsString() + "');")
55 |
56 | 2000
57 |
58 |
59 |
60 | clock;time;watch
61 |
64 |
65 |
66 |
67 | ^wait$|^z$
68 |
81 |
82 |
83 |
84 | true
85 |
99 |
100 |
101 |
120 |
121 |
122 |
126 |
159 |
160 |
161 |
165 |
166 |
167 |
168 |
169 |
170 |
173 |
174 | game_clock.increment = minutes
175 |
176 |
177 |
178 |
181 |
182 | time = game_clock.time + time
183 | o = null
184 | while (o = null) {
185 | o = AttemptCreateEvent(time)
186 | time = time + 1
187 | }
188 | o.look = script
189 | o.alias = alias
190 |
191 |
192 |
195 |
196 | game_clock.nextstep = step
197 | game_clock.countdown = delay
198 | //msg("delay=" + delay)
199 |
200 |
201 |
202 |
203 |
207 |
208 | minutes = time % 60
209 | hours24 = (time / 60) % 24
210 | days = time / (60 * 24)
211 | name = "event_" + DD(days) + "_" + DD(hours24) + "_" + DD(minutes)
212 | //msg("Setting for: " + name)
213 | o = GetObject(name)
214 | if (o = null) {
215 | create(name)
216 | return (GetObject(name))
217 | }
218 | else {
219 | return (null)
220 | }
221 |
222 |
223 |
227 |
228 | if (TypeOf(minutes) = "string") {
229 | l = Split(minutes, ":")
230 | if (not ListCount(l) = 3) error("SetTime failed to understand " + minutes)
231 | game_clock.days = ToInt(StringListItem(l, 0))
232 | game_clock.hours24 = ToInt(StringListItem(l, 1))
233 | game_clock.minutes = ToInt(StringListItem(l, 2))
234 | game_clock.time = (game_clock.days * 24 + game_clock.hours24) * 60 + game_clock.minutes
235 | }
236 | else {
237 | game_clock.time = minutes
238 | game_clock.minutes = game_clock.time % 60
239 | game_clock.hours24 = (game_clock.time / 60) % 24
240 | game_clock.days = game_clock.time / (60 * 24) + 1
241 | }
242 | if (not GetObject("NpcTurnScript") = null) {
243 | DisableTurnScript (NpcTurnScript)
244 | }
245 | game.clock = TimeAsString()
246 |
247 |
248 |
251 | time)
261 | ]]>
262 |
263 |
267 | time)
277 | ]]>
278 |
279 |
282 |
283 | return (game_clock.time)
284 |
285 |
286 |
289 |
292 |
293 |
294 |
297 |
305 |
306 |
307 |
311 |
314 |
315 |
316 |
321 |
327 |
328 |
329 |
338 |
339 | year = game_clock.startyear
340 | day = game_clock.days
341 | if (1 > day) error("Date function cannot cope with a day of zero or less")
342 | // what year is it?
343 | flag = true
344 | while (flag) {
345 | if (year % 4 = 0) {
346 | days_this_year = 366
347 | }
348 | else {
349 | days_this_year = 365
350 | }
351 | if (day > days_this_year) {
352 | year = year + 1
353 | day = day - days_this_year
354 | }
355 | else {
356 | flag = false
357 | }
358 | }
359 | // days in month
360 | if (year % 4 = 0) {
361 | days_in_months = Split("31;29;31;30;31;30;31;31;30;31;30;31", ";")
362 | }
363 | else {
364 | days_in_months = Split("31;28;31;30;31;30;31;31;30;31;30;31", ";")
365 | }
366 | // what month is it?
367 | month = 1
368 | for (i, 0, 11) {
369 | days_in_month = ToInt(StringListItem(days_in_months, i))
370 | if (day > days_in_month) {
371 | month = month + 1
372 | day = day - days_in_month
373 | }
374 | else {
375 | return (DisplayDate(year, month, day))
376 | }
377 | }
378 |
379 |
380 |
383 |
384 | months = Split(";January;February;March;April;May;June;July;August;September;October;November;December", ";")
385 | return ("" + day + "th of " + StringListItem(months, month) + ", " + year)
386 |
387 |
388 |
--------------------------------------------------------------------------------
/CompliantNpcLib.aslx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
22 |
23 |
24 |
25 | "Tell " + object.article + " all you want, " + object.gender + "'s not going to do anything."
26 |
27 |
28 |
29 |
30 |
31 |
32 | .*)$|^go (?.*)$|^(?north|east|south|west|northeast|northwest|southeast|southwest|in|out|up|down|n|e|s|w|ne|nw|se|sw|o|u|d)$]]>
33 | [UnresolvedLocation]
34 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
80 |
81 |
82 |
83 |
84 | .*) to|(?.*),) go to (?.*)$|^(?.*), go (?.*)$]]>
85 | You can't go there.
86 |
89 |
90 |
91 | .*) to|(?.*),) (go |)(?north|east|south|west|northeast|northwest|southeast|southwest|in|out|up|down|n|e|s|w|ne|nw|se|sw|o|u|d)$]]>
92 | You can't go there.
93 |
96 |
97 |
98 | // WARNING: This does not allow for doors that are stopped by scripts
99 | if (not DoesInherit(npc, "compliant_npc")) {
100 | msg(DynamicTemplate("PosturesNotNpc", npc))
101 | }
102 | else if (not exit.visible) {
103 | msg ([UnresolvedLocation])
104 | }
105 | else {
106 | do (npc, "requestgo", QuickParams("object", exit))
107 | }
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | .*) to|(?.*),) (follow me|follow)$]]>
116 |
124 |
125 |
126 |
127 | .*) to|(?.*),) (stop following|don't follow|do not follow|wait here|wait)( me|)$]]>
128 |
136 |
137 |
138 |
139 |
140 |
141 |
142 | .*) to|(?.*),) (get|take|pick up) (?.*)$]]>
143 |
160 |
161 |
162 |
163 | .*) to|(?.*),) (drop) (?.*)$]]>
164 | none
165 |
166 | foreach (npc, FilterByType(ScopeVisibleNotHeldForRoom (game.pov.parent), "compliant_npc")) {
167 | foreach (obj, GetDirectChildren(npc)) {
168 | list add (items, obj)
169 | }
170 | }
171 |
172 |
183 |
184 |
185 |
186 | .*) to|(?.*),) (give me|give) (?.*)$]]>
187 | none
188 |
189 | foreach (npc, FilterByType(ScopeVisibleNotHeldForRoom (game.pov.parent), "compliant_npc")) {
190 | foreach (obj, GetDirectChildren(npc)) {
191 | list add (items, obj)
192 | }
193 | }
194 |
195 |
198 |
199 |
200 | .*) to|(?.*),) (give) (?.*) to (?.*)$]]>
201 | none
202 |
203 | foreach (npc, FilterByType(ScopeVisibleNotHeldForRoom (game.pov.parent), "compliant_npc")) {
204 | foreach (obj, GetDirectChildren(npc)) {
205 | list add (items, obj)
206 | }
207 | }
208 |
209 |
212 |
213 |
214 | if (not DoesInherit(npc, "compliant_npc")) {
215 | msg(DynamicTemplate("PosturesNotNpc", npc))
216 | }
217 | else if (not object.parent = npc) {
218 | msg(WriteVerb(npc, "do") + " not have " + object.article + ".")
219 | }
220 | else {
221 | msg ("Giving " + object.name + " to " + subject.name)
222 | do(npc, "requestgive", QuickParams("object", object, "subject", subject))
223 | }
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 | 10
242 | true
243 | Okay!
244 | 'I'd rather not.'
245 | 'I don't think so.'
246 | 'Not happening.'
247 | 'No way!'
248 | 'In your dreams, creep!'
249 |
250 |
251 |
252 |
253 | // level is an int
254 | // you could have compliance drop if degree is big enough -
255 | // the NPC is so horrified he is less likely to agree in future
256 | if (not IsDefined("level")) level = 10
257 | degree = (level - this.compliance) / 3
258 | if (degree > 4) degree = 4
259 | if (degree >= 0) {
260 | this.complies = false
261 | msg(GetString(this, "nomsg" + degree))
262 | }
263 | else {
264 | this.complies = true
265 | }
266 |
267 |
268 |
269 |
270 | do (this, "checkagreement", QuickParams("level", 12))
271 | if (this.complies) {
272 | if (HasScript(object, "npc_take")) {
273 | do (object, "npc_take", QuickParams("npc", npc))
274 | }
275 | else if ((HasBoolean(object, "npc_take") and not GetBoolean(object, "npc_take")) or (not HasAttribute(object, "npc_take") and not GetBoolean(object, "take"))) {
276 | msg ("'I can't get that,' says " + GetDefiniteName(this) + ".")
277 | }
278 | else {
279 | msg ("'" + this.yesmsg + "' says " + CapFirst(GetDefiniteName(this)) + ", picking " + GetDefiniteName(object) + " up.")
280 | object.parent = this
281 | }
282 | }
283 |
284 |
285 |
286 | do (this, "checkagreement", QuickParams("level", 12))
287 | if (this.complies) {
288 | if (HasScript(object, "npc_drop")) {
289 | do (object, "npc_drop", QuickParams("npc", this))
290 | }
291 | else if ((HasBoolean(object, "npc_drop") and not GetBoolean(object, "npc_drop")) or (not HasAttribute(object, "npc_drop") and not GetBoolean(object, "drop"))) {
292 | msg ("'I can't drop that,' says " + GetDefiniteName(this) + ".")
293 | }
294 | else {
295 | msg ("'" + this.yesmsg + "' says " + CapFirst(GetDefiniteName(this)) + ", dropping " + GetDefiniteName(object) + ".")
296 | object.parent = this.parent
297 | }
298 | }
299 |
300 |
301 |
302 | do (this, "checkagreement", QuickParams("level", 12))
303 | if (this.complies) {
304 | if (HasScript(this, "give_" + object.name + "_to_" + subject.name)) {
305 | do (this, "give_" + object.name + "_to_" + subject.name)
306 | }
307 | else if (HasScript(this, "give_" + object.name)) {
308 | do (this, "give_" + object.name + "_to_" + subject.name, QuickParams("subject", subject))
309 | }
310 | else if ((HasBoolean(object, "npc_drop") and not GetBoolean(object, "npc_drop")) or (not HasAttribute(object, "npc_drop") and not GetBoolean(object, "drop"))) {
311 | msg ("'I can't drop that,' says " + GetDefiniteName(this) + ".")
312 | }
313 | else {
314 | if (subject.gender = "you") {
315 | target = "you"
316 | }
317 | else {
318 | target = GetDefiniteName(subject)
319 | }
320 | msg ("'" + this.yesmsg + "' says " + CapFirst(GetDefiniteName(this)) + ", giving " + GetDefiniteName(object) + " to " + target + ".")
321 | object.parent = subject
322 | }
323 | }
324 |
325 |
326 |
327 | do (this, "checkagreement", QuickParams("level", 8))
328 | if (this.complies) {
329 | if (object.locked) {
330 | msg ("'It's locked,' says " + GetDefiniteName(this) + ".")
331 | }
332 | else {
333 | if (this.posture = null) {
334 | msg ("'" + this.yesmsg + "' says " + CapFirst(GetDefiniteName(this)) + ", heading " + object.alias + ".")
335 | }
336 | else if (this.posture_object = null) {
337 | msg ("'" + this.yesmsg + "' says " + GetDefiniteName(this) + ", standing up and going " + object.alias + ".")
338 | }
339 | else {
340 | msg ("'" + this.yesmsg + "' says " + GetDefiniteName(this) + ", getting off " + GetDefiniteName(this.posture_object) + ", and walking " + object.alias + "wards.")
341 | }
342 | this.posture_object = null
343 | this.posture = null
344 | this.listalias = this.alias
345 | this.parent = object.to
346 | }
347 | }
348 |
349 |
350 |
351 | do (this, "checkagreement", QuickParams("level", 8))
352 | if (this.complies) {
353 | if (this.following = game.pov) {
354 | msg ("'I am!' says " + GetDefiniteName(this) + ".")
355 | }
356 | else {
357 | msg ("'" + this.yesmsg + "' says " + GetDefiniteName(this) + ", looking expectantly at you.")
358 | this.following = game.pov
359 | }
360 | }
361 |
362 |
363 |
364 | do (this, "checkagreement", QuickParams("level", 20))
365 | if (this.complies) {
366 | if (this.following = null) {
367 | msg ("'I am!' says " + GetDefiniteName(this) + ".")
368 | }
369 | else {
370 | msg ("'" + this.yesmsg + "' says " + GetDefiniteName(this) + ", tapping " + this.possessive + " foot.")
371 | this.following = game.pov
372 | }
373 | }
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
--------------------------------------------------------------------------------
/SaveLoad.aslx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
20 |
21 |
22 |
23 |
25 |
26 |
27 | saveLoad = {
28 | debug:false,
29 |
30 | saveGame:function(title, filename, data) {
31 | if (!this.lsTest()) return;
32 | var currentdate = new Date();
33 | var s = title + "|";
34 | s += currentdate.toLocaleString() + "|";
35 | if (!this.debug) {
36 | localStorage.setItem(title + ": " + filename, s + data);
37 | }
38 | else {
39 | this.lastSave = s + data
40 | }
41 | addText("Saved: " + filename + " ");
42 | },
43 |
44 | loadGame:function(title, filename) {
45 | if (!this.lsTest()) return;
46 | if (!this.debug) {
47 | var data = localStorage.getItem(title + ": " + filename);
48 | }
49 | else {
50 | var currentdate = new Date();
51 | data = this.lastSave;
52 | }
53 | if (data === null) {
54 | addText("Failed to find file: " + filename);
55 | return;
56 | }
57 | var arr = data.split("|");
58 | arr.shift();
59 | arr.shift();
60 | ASLEvent("LoadGame", arr.join("|"));
61 | },
62 |
63 | deleteGame:function(title, filename) {
64 | if (!this.lsTest()) return;
65 | if (!this.debug) {
66 | localStorage.removeItem(title + ": " + filename);
67 | }
68 | addText("Deleted:" + filename);
69 | },
70 |
71 | dirGame:function(title) {
72 | if (!this.lsTest()) return;
73 | var s = "
Filename
Timestamp
";
74 | if (!this.debug) {
75 | $.each(localStorage, function(key, value){
76 | var regex = new RegExp("^" + title + ": ");
77 | var name = key.replace(regex, "");
78 | if (regex.test(key)) {
79 | var arr = value.split("|");
80 | s += "
" + name + "
";
81 | s += "
" + arr[1] + "
";
82 | }
83 | });
84 | }
85 | s += "
";
86 | addText(s);
87 | },
88 |
89 | lsTest:function() {
90 | if (this.debug) return true;
91 | if (platform === "desktop") {
92 | alert("Cannot save (localStorage not available). Save and load via the File menu instead.");
93 | return false;
94 | }
95 | var test = 'test';
96 | try {
97 | localStorage.setItem(test, test);
98 | localStorage.removeItem(test);
99 | return true;
100 | } catch(e) {
101 | alert("Cannot save (localStorage not available).");
102 | return false;
103 | }
104 | },
105 | };
106 |
107 | ]]>
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | ^(save|load|restore)$
116 |
120 |
121 |
122 |
123 | save #text#
124 |
130 |
131 |
132 |
133 | load #text#;restore #text#
134 |
137 |
138 |
139 |
140 | del #text#;delete #text#
141 |
145 |
146 |
147 |
148 | dir;ls
149 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
171 |
172 | allowedTypes = Split("object;list;int;integer;boolean;flag;dictionaryoflists")
173 | if (not HasAttribute(game, "saveloadatts")) {
174 | msg("Error: Save/load not properly implemented - no game.saveloadatts attribute set.")
175 | msg("")
176 | return (false)
177 | }
178 | if (not TypeOf(game, "saveloadatts") = "stringlist") {
179 | msg("Error: Save/load not properly implemented - the game.saveloadatts attribute must be a string list.")
180 | msg("")
181 | return (false)
182 | }
183 | foreach (s, game.saveloadatts) {
184 | if (StartsWith(s, "player:parent:")) {
185 | msg("Error: Save/load not properly implemented - the game.saveloadatts list includes player.parent.")
186 | msg("")
187 | return (false)
188 | }
189 | arr = Split(s, ".")
190 | if (not ListCount(arr) = 3) {
191 | msg("Error: Save/load not properly implemented - the game.saveloadatts list includes a badly formatted attribute; " + s + " (should have three parts separated by dots).")
192 | msg("")
193 | return (false)
194 | }
195 | if (not ListContains(allowedTypes, arr[2])) {
196 | msg("Error: Save/load not properly implemented - the game.saveloadatts list includes a badly formatted attribute; " + s + " (third part should be one of " + Join(allowedTypes, ", ") + "; not " + arr[2] + ").")
197 | msg("")
198 | return (false)
199 | }
200 | }
201 |
202 | foreach (obj, AllObjects()) {
203 | if (not obj = player) {
204 | list add (game.saveloadatts, obj.name + ".parent.object")
205 | }
206 | }
207 | AddAtts(game, game.saveloadints, "int")
208 | AddAtts(game, game.saveloadflags, "flag")
209 | AddAtts(player, player.saveloadints, "int")
210 | AddAtts(player, player.saveloadflags, "flag")
211 | list add (game.saveloadatts, "game.textprocessor_seen.dictionaryoflists")
212 | list add (game.saveloadatts, "game.roomsvisited.string")
213 | list add (game.saveloadatts, "game.exitslocked.string")
214 | list add (game.saveloadatts, "game.exitsnotvisible.string")
215 | list add (game.saveloadatts, "game.itemslocked.string")
216 | list add (game.saveloadatts, "game.itemsopen.string")
217 | list add (game.saveloadatts, "game.itemsworn.string")
218 | list add (game.saveloadatts, "game.itemshidden.string")
219 | list add (game.saveloadatts, "game.itemsdisplay.string")
220 | list add (game.saveloadatts, "game.clonedata.string")
221 | list add (game.saveloadatts, "player.current_location.object")
222 |
223 | JS.addScript (saveloaddata.saveloadscript)
224 | return (true)
225 |
226 |
227 | if (not values = null) {
228 | values = Split(values, ";")
229 | for (i, 0, ListCount(values) - 1) {
230 | list add (game.saveloadatts, obj.name + "." + values[i] + "." + typename)
231 | }
232 | }
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 | msg("LoadGame")
261 | PreLoad
262 | pos = 0
263 | foreach (val, Split(s, ";")) {
264 | ary = Split(StringListItem(game.saveloadatts, pos), ".")
265 | obj = GetObject(StringListItem (ary, 0))
266 | att = StringListItem (ary, 1)
267 | type = LCase(StringListItem (ary, 2))
268 | if (val = "" or TypeOf(val) = "null") {
269 | set (obj, att, null)
270 | }
271 | else if (type = "object") {
272 | set (obj, att, GetObject(val))
273 | }
274 | else if (type = "list") {
275 | set (obj, att, Split(val, "|"))
276 | }
277 | else if (type = "int" or type = "integer") {
278 | if (IsInt(val)) {
279 | set (obj, att, ToInt(val))
280 | }
281 | else {
282 | error("Load error: Cannot convert \"" + val + "\" to an integer for " + StringListItem(game.saveloadatts, pos))
283 | }
284 | }
285 | else if (type = "boolean" or type = "flag") {
286 | set (obj, att, LCase(val) = "true")
287 | }
288 | else if (type = "dictionaryoflists") {
289 | set (obj, att, SuperSplit(val))
290 | }
291 | else {
292 | set (obj, att, Replace(val, "@@@semicolon@@@", ";"))
293 | }
294 | pos = pos + 1
295 | }
296 |
297 | SetAll(game.roomsvisited, "visited", true)
298 | SetAll(game.exitslocked, "locked", true)
299 | SetAll(game.exitsnotvisible, "visible", false)
300 | SetAll(game.itemslocked, "locked", true)
301 | SetAll(game.itemsopen, "isopen", true)
302 | SetAll(game.itemsworn, "worn", true)
303 | SetAll(game.itemshidden, "hidden", true)
304 | SetAll(game.itemsdisplay, "display", true)
305 | ol = FilterByNotAttribute(AllObjects(), "prototype", null)
306 | while (not ListCount(ol) = 0) {
307 | o = ObjectListItem(ol, 0)
308 | destroy(o.name)
309 | ol = FilterByNotAttribute(AllObjects(), "prototype", null)
310 | }
311 | SetCloneData(game.clonedata)
312 |
313 | PostLoad
314 | player.parent = player.current_location
315 | msg("Game loaded")
316 |
317 |
318 |
319 |
320 |
321 | // First collect the standard data, and add to the game object
322 | player.current_location = player.parent
323 | // For rooms
324 | game.roomsvisited = ListWith(AllObjects(), "visited", true)
325 | // For exits
326 | game.exitslocked = ListWith(AllExits(), "locked", true)
327 | game.exitsnotvisible = ListWith(AllExits(), "visible", false)
328 | // For containers
329 | game.itemslocked = ListWith(AllObjects(), "locked", true)
330 | game.itemsopen = ListWith(AllObjects(), "isopen", true)
331 | // For wearables
332 | game.itemsworn = ListWith(AllObjects(), "worn", true)
333 | // For conversations
334 | game.itemshidden = ListWith(AllObjects(), "hidden", true)
335 | game.itemsdisplay = ListWith(AllObjects(), "display", true)
336 |
337 | game.clonedata = GetCloneData()
338 |
339 | data = NewStringList()
340 | foreach (attri, game.saveloadatts) {
341 | ary = Split(attri, ".")
342 | obj = GetObject(StringListItem (ary, 0))
343 | if (not ListCount(ary) = 3) {
344 | error("Save error: Badly formatted entry: " + attri)
345 | }
346 | else if (obj = null) {
347 | error("Save error: Failed to find an object called: " + StringListItem (ary, 0))
348 | }
349 | else {
350 | att = StringListItem (ary, 1)
351 | type = LCase(StringListItem (ary, 2))
352 | val = GetAttribute(obj, att)
353 | if (TypeOf(val) = "null") {
354 | list add (data, "")
355 | }
356 | else if (type = "object") {
357 | if (not TypeOf(val) = "object") error("Save: Expected " + attri + ", found " + TypeOf(val))
358 | list add (data, val.name)
359 | }
360 | else if (type = "list") {
361 | if (not TypeOf(val) = "stringlist") error("Save: Expected " + attri + ", found " + TypeOf(val))
362 | list add (data, Join(val, "|"))
363 | }
364 | else if (type = "int" or type = "integer") {
365 | if (not TypeOf(val) = "int") error("Save: Expected " + attri + ", found " + TypeOf(val))
366 | list add (data, "" + val)
367 | }
368 | else if (type = "boolean" or type = "flag") {
369 | if (not TypeOf(val) = "boolean") error("Save: Expected " + attri + ", found " + TypeOf(val))
370 | list add (data, "" + val)
371 | }
372 | else if (type = "dictionaryoflists") {
373 | list add (data, SuperJoin(val))
374 | }
375 | else if (type = "string") {
376 | if (not TypeOf(val) = "string") error("Save: Expected " + attri + ", found " + TypeOf(val))
377 | list add (data, Replace(val, ";", "@@@semicolon@@@"))
378 | }
379 | else {
380 | error("Save error: Invalid type for " + StringListItem (ary, 0) + ": " + type)
381 | }
382 | }
383 | }
384 |
385 | PreSave
386 | //msg("here3")
387 | return (Join(data, ";"))
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
408 |
409 | l = FilterByAttribute(list, att, val)
410 | return (Join(ObjectListToStringList(l, "name"), "|"))
411 |
412 |
413 | if (not s = null and not s = "") {
414 | l = Split(s, "|")
415 | foreach (s, l) {
416 | o = GetObject(s)
417 | if (o = null) error ("Failed to find object: " + s)
418 | set (o, att, val)
419 | }
420 | }
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 | ol = FilterByNotAttribute(AllObjects(), "prototype", null)
430 | sl = NewStringList()
431 | msg("About to do clones")
432 | foreach (o, ol) {
433 | s = o.name + "/" + o.prototype.name
434 | if (HasAttribute(o, "saveloadatts")) {
435 | foreach (att, o.saveloadatts) {
436 | s = s + "/" + GetAttribute(o, att)
437 | }
438 | list add (sl, s)
439 | }
440 | else {
441 | error("Clone prototype, " + o.prototype.name + ", has no 'saveloadatts' attribute.")
442 | }
443 | }
444 | return (Join(sl, "|"))
445 |
446 |
447 |
448 | if (not str = null) {
449 | foreach (s, Split(str, "|")) {
450 | l = Split(s, "/")
451 | prototype = GetObject(StringListItem(l, 1))
452 | o = CloneObject(prototype)
453 | if (not o.name = StringListItem(l, 0)) error ("Name mismatch in clones: " + o.name + " is not " + StringListItem(l, 0))
454 | list remove (l, prototype.name)
455 | list remove (l, o.name)
456 | for (i, 0, ListCount(l) - 1) {
457 | val = StringListItem(l, i)
458 | att = StringListItem(o.saveloadatts, i)
459 | if (val = "") {
460 | set (o, att, null)
461 | }
462 | else if (IsInt(val)) {
463 | set (o, att, ToInt(val))
464 | }
465 | else if (val = "True") {
466 | set (o, att, true)
467 | }
468 | else if (val = "False") {
469 | set (o, att, false)
470 | }
471 | else {
472 | set (o, att, val)
473 | }
474 | }
475 | }
476 | }
477 |
478 |
479 |
480 |
481 |
482 |
483 |
489 |
490 | sublist = NewStringList()
491 | foreach (key, col) {
492 | val = DictionaryItem(col, key)
493 | s2 = Join(ToStringList(val), "#")
494 | s = key + "~" + s2
495 | list add (sublist, s)
496 | }
497 | return(Join(sublist, "|"))
498 |
499 |
500 | dict = NewDictionary()
501 | list = Split(str, "|")
502 | foreach (s, list) {
503 | sublist = Split(s, "~")
504 | key = StringListItem(sublist, 0)
505 | value = StringListItem(sublist, 1) // here
506 | dictionary add(dict, key, Split(value, "#"))
507 | }
508 | return(dict)
509 |
510 |
511 | sl = NewStringList()
512 | foreach (el, col) {
513 | list add (sl, ToString(el))
514 | }
515 | return(sl)
516 |
517 |
518 |
519 |
522 |
523 | if (not HasAttribute(object, "saveloadatts")) {
524 | error ("Cannot clone an object, " + object.name + ", with no 'saveloadatts' set, as it will not save properly.")
525 | return (null)
526 | }
527 | if (not TypeOf(object, "saveloadatts") = "stringlist") {
528 | error ("Cannot clone an object, " + object.name + ", as 'saveloadatts' is not a string list.")
529 | return (null)
530 | }
531 |
532 | newobject = ShallowClone(object)
533 | if (not HasString(object, "alias")) {
534 | newobject.alias = object.name
535 | }
536 | if (not HasAttribute(object, "prototype")) {
537 | newobject.prototype = object
538 | }
539 | foreach (o, GetDirectChildren(object)) {
540 | o2 = CloneObject (o)
541 | MoveObject (o2, newobject)
542 | }
543 | return (newobject)
544 |
545 |
546 |
547 |
--------------------------------------------------------------------------------