Invie
Member
-
Joined
-
Last visited
Reputation Activity
-
Invie got a reaction from Seigheart in The Cartographer's Cipher307-517-3-7B4862CB
-
Invie reacted to Seigheart in Seigheart's Guide to MDScriptMDScript for Players: What I Learned Building Clickies
======================================================
Hi all, Seigheart here.
I built the Primordial Keeper, the Primordial Archive and the Cartographer's Cipher, and along the way I ran into pretty much every wall MDScript has. So I've put together what I wish someone had handed me at the start. It's all taken from the official MD Script Manual on the forum and from scripts that actually run in game. Where I'm not sure about something, I'll say so.
What It Is and Where It Goes
----------------------------
MDScript is a cut-down PHP that runs on the server whenever someone clicks your clicky. No classes, no $ variables. You get a fixed set of @ variables and that's it.
Open your clicky with "edit own" and you'll see four fields: Title at the top, Content on the left, Script on the right, and Password at the bottom. Hit save&compile to apply your changes.
Content holds HTML: text, images, forms. Only the part between <body> and </body> gets used, and newlines are ignored because it's HTML, so use <p> or <br>.
Here's the thing that confuses everyone at first. If the Script box is empty, your Content shows as it is. The moment the Script box has anything in it, the Content disappears until your script does echo @content[0];.
You can cut the Content box into pieces with this exact line:
<!-- content separator -->
The pieces become @content[0], @content[1] and so on, starting at 0. It has to say "content separator", not "content section". Then you can show different pieces under different conditions. Plenty of us just leave Content empty and print everything from the Script box with echo. That's what I do.
One more thing: what you see in the editor right after save&compile can differ from what a normal visitor sees, and that includes storage. Always test as a visitor.
Your First Script
-----------------
Every script needs a locations line:
(locations 1_0x0_1)
No quotes, no ; at the end. For several locations, separate them with commas and no spaces, e.g. (locations 1_0x0_1,1_1x1_1). You get 12 at most. Variables don't work in it.
The editor shows the right line for your spot above the code field ("Add location setting: (locations X)"). Put it on the first line. The manual says "anywhere", but the error message says first line, so I go with the error message.
For reference, 1_0x0_1 is the Gazebo of Equilibrium. I'm not 100% sure what each number in a coordinate means, so don't take my word on that.
Watch out for this one: an "incorrect location" error can show up when the real mistake is somewhere else in your code entirely.
Printing is easy. echo and print write HTML into the page:
(locations 1_0x0_1) echo "<p>Hello, traveller!</p>";
Variables are where it gets odd. You can't make your own. You get @va to @vz (26 general ones), plus @tpl, @temp and @log, which work the same way and just have friendlier names. Then there are the special ones: @input (form data), @content (Content pieces) and @storage (saved data).
Even loop counters have to come from that set: for (@vi = 0; @vi < 4; @vi++) { ... }. foreach (@vp as @vk => @vh) works fine. Arrays work too, so one variable can hold a lot: @vu['colour'] = 'gold';.
Forms and @input
----------------
Put a form in your Content box or echo one from your script:
<form method="post" action=""> <button type="submit" name="go" value="A">Option A</button> </form>
It posts back to the same clicky, and whatever was sent shows up in @input:
if (isset(@input['go']) and @input['go'] == 'A') { echo "You picked A"; }
$_POST isn't allowed. Always use @input.
Now, two gotchas. First, field names. A field name containing a banned bit of text breaks the script. The forum example is a field with "val" in its name, which had to be renamed hidden_button.
Second, and this one bit me constantly: the word "value" itself. The filter checks your whole script, strings included, and "value" contains "val". If you echo your buttons from the Script box, build the word in pieces:
@vv = 'va' . 'lue'; echo "<button type='submit' name='go' " . @vv . "='A'>Option A</button>";
HTML typed straight into the Content box isn't part of your script, so value="Yes" is fine there. The official tutorial does exactly that.
Always check what comes in, because players can send anything. Use isset() first, trim() it, compare it to the exact things you expect, and wrap anything you print back in htmlspecialchars() or strip_tags(). For numbers, check it's only digits, e.g. strspn(@vx, '0123456789') == strlen(@vx).
There's no JavaScript button handling here. Every button is just another post back to the server.
Remembering Things
------------------
Storage with mds_storage()
This is the main way to keep data:
@vo = mds_storage('myname', 'toau');
It gives you back a number. From then on, read and write @storage[@vo], and whatever's in there gets saved. The second part is the type:
- totu: this object, this user
- toau: this object, all users
- aotu: all objects, this user
- aoau: all objects, all users (kept apart per editor)
The same name with a different type is a different storage. You can't read another editor's storage, and an empty storage gets deleted.
Start it as an array the first time. If it ends up as a plain number, later writes fail with "Cannot use a scalar value as an array". This is the opener I use:
if (!isset(@storage[@vo]) or is_scalar(@storage[@vo])) { @storage[@vo] = array(); }
For one record per player inside a shared storage: @storage[@vo][uv('name')] = ...;
I haven't tested the size limits myself, or what happens if two players save in the exact same instant. My guess is the last write wins, but I don't know for sure.
The old mds_storage_load / mds_storage_read names reportedly get rejected because they contain "load" and "read". Just use mds_storage().
store() and retrieve()
store(@vh); in one item and retrieve(@vh); in another. It can hold whole arrays. The forum says it's one value per scripter and player, but I haven't checked that myself.
Session Data
This is the temporary, fast option. mds_store_sessdata(value, box) (alias storetmp) saves, and mds_retrieve_sessdata(@holder, box) (alias retrievetmp) reads.
You get 10 boxes (0 to 9) per player, and each editor has their own set. Strings only, max 250 characters, so serialize() arrays first. It lasts until the player logs out and is shared by all your items.
Keys
Keys are yes/no flags on the player:
mds_give_rpcq_keys('zq77-door'); // give mds_has_rpcq_keys('zq77-a,zq77-b') // true only if the player has ALL of them mds_take_rpcq_keys('zq77-door'); // take away
They're comma-separated text, no arrays. And they're global: any script checking the same name sees the same key. The game saves them as rpcq-<name>. So pick a unique, secret prefix, or someone will collide with you or fake your keys.
Keys aren't for keeping numbers. Use storage for counts.
Where keys really shine is linking two clickies. That's how I connected the Primordial Keeper and the Cartographer's Cipher, and it's how you'd build a quest that starts at one clicky and ends at another. One thing I'm not sure of: whether a key you give in this click can be checked in the same click. I build around it so it doesn't matter.
Reading the Player
------------------
uv('name') reads facts about whoever is clicking. It's read only. The names I know of:
id, ve, vp, xpl, maxve, maxvp, land, alliance, age (active days), loyalty, honor, name, mp, heads, won, lost, avatar_level (0 none, 1 B/W, 2 gold access), avatar, xp, kills, illusion, location (coordinates text), stored_heat, and since 2013: tag, description, principles, landscore.
Funny one: "description" contains a banned piece, so you have to write uv('descri' . 'ption').
Land numbers are 1 No Homeland, 2 Marind Bell, 3 Loreroot, 4 Golemus, 5 Necrovion, 6 Underground, 7 Archives, 8 No Mans Land, 9 unknown, 10 Lands of the East.
date('z') gives you the MD day (day of the year). Server time zone is Europe/Helsinki.
A few other checks on the player:
- mds_has_item('Silver coin'): how many of that item they hold. Coins and resources count.
- mds_is_itc('ITC...MDI'): checks an item transfer code and gives back its details, or false.
- mds_is_ctc('CTC...MDC'): checks a creature transfer code and gives back the creature's details, or false.
- mds_location_visits('current'): how often they've been here. Handy for hiding spoilers.
- mds_player_heat(), mds_get_resource_count(), mds_current_weather().
Fair warning: you can only check items. Nothing documented lets a script give or take items, creatures or quests. Quests get built out of keys and storage.
Examples
--------
All six of these pass a PHP syntax check and a banned-word scan. Swap 1_0x0_1 for your own location, and change the zq77- key prefix and the storage names to your own. The real test is still save&compile in game.
Hello and a Click Counter
(locations 1_0x0_1) // Hello and a shared counter for this clicky. @va = uv('name'); @vo = mds_storage('myhellocount', 'toau'); if (!isset(@storage[@vo]) or is_scalar(@storage[@vo])) { @storage[@vo] = array(0); } @storage[@vo][0]++; echo "<p>Hello, " . htmlspecialchars(@va) . "!</p>"; echo "<p>This clicky has been clicked " . @storage[@vo][0] . " times.</p>";
A Button Menu
(locations 1_0x0_1) // A menu of buttons. Each button posts go=A, go=B or go=C. @vv = 'va' . 'lue'; echo "<form method='post' action=''>"; echo "<button type='submit' name='go' " . @vv . "='A'>Lore</button> "; echo "<button type='submit' name='go' " . @vv . "='B'>Map tip</button> "; echo "<button type='submit' name='go' " . @vv . "='C'>Who am I?</button>"; echo "</form>"; @vg = isset(@input['go']) ? trim(@input['go']) : ''; if (@vg == 'A') { echo "<p>Long ago, a gazebo stood here in perfect balance.</p>"; } elseif (@vg == 'B') { echo "<p>Look for clickies near the stairs.</p>"; } elseif (@vg == 'C') { echo "<p>You are " . htmlspecialchars(uv('name')) . ", with " . uv('age') . " active days.</p>"; }
A Once-a-Day Greeting
(locations 1_0x0_1) // Once per MD day per player. date('z') is the day of the year. @va = uv('name'); @vd = date('Y') . '-' . date('z'); @vo = mds_storage('mydailygreet', 'toau'); if (!isset(@storage[@vo]) or is_scalar(@storage[@vo])) { @storage[@vo] = array(); } if (isset(@storage[@vo][@va]) and @storage[@vo][@va] == @vd) { echo "<p>You have had your greeting today. Come back tomorrow!</p>"; } else { @storage[@vo][@va] = @vd; echo "<p>Good day, " . htmlspecialchars(@va) . "! Here is your daily blessing.</p>"; }
A Small Quest with Keys
(locations 1_0x0_1) // A three step quest kept in keys. Pick your own odd prefix so nobody guesses it. @vv = 'va' . 'lue'; @vg = isset(@input['go']) ? trim(@input['go']) : ''; if (mds_has_rpcq_keys('zq77-step2')) { echo "<p>The quest is complete. Well done!</p>"; } elseif (mds_has_rpcq_keys('zq77-step1')) { if (mds_has_item('Silver coin') >= 1) { mds_give_rpcq_keys('zq77-step2'); echo "<p>You show the silver coin. The quest is complete!</p>"; } else { echo "<p>Step 2: come back holding a Silver coin.</p>"; } } elseif (@vg == 'S') { mds_give_rpcq_keys('zq77-step1'); echo "<p>Quest started. Step 2: come back holding a Silver coin.</p>"; } else { echo "<form method='post' action=''><p>A stranger asks for help.</p>"; echo "<button type='submit' name='go' " . @vv . "='S'>Accept the quest</button></form>"; }
A Riddle Door with a Typed Answer
(locations 1_0x0_1) // A riddle door. The form field is named 'guess' (a field name holding v-a-l fails). @vv = 'va' . 'lue'; if (mds_has_rpcq_keys('zq77-door')) { echo "<p>The door is unlocked for you.</p>"; } else { @vg = isset(@input['guess']) ? strtolower(trim(strip_tags(@input['guess']))) : ''; if (@vg == 'echo') { mds_give_rpcq_keys('zq77-door'); echo "<p>Correct! The door swings wide.</p>"; } else { if (@vg != '') { echo "<p>Wrong. Think again.</p>"; } echo "<form method='post' action=''>"; echo "<p>I speak without a mouth and hear without ears. What am I?</p>"; echo "<input type='te" . "xt' name='guess' maxlength='30'> "; echo "<button type='submit' name='go' " . @vv . "='1'>Answer</button></form>"; } }
Notice the 'te' . 'xt'. "Text" is on my cautious list below.
Content Pieces (from the Official Beginner Tutorial)
Content box:
<form method="post"><input type="submit" name="wizard" value="Yes"/></form><!-- content separator --><p>Then go to the next room.</p>
Script box:
(locations 1_0x0_1) // Content box holds: a Yes button, then the separator, then a reply. echo @content[0]; if (isset(@input['wizard']) and @input['wizard'] == 'Yes') { echo @content[1]; }
The Word Filter
---------------
This is the part that cost me the most time. The filter is a plain text check over your whole script: code, strings and comments. It doesn't care about grammar. If a banned piece shows up anywhere, even buried inside a longer word, you get one of these: [STRICT RESTRICTION], [GENERAL RESTRICTION], [LANGUAGE RESTRICTION] (function not supported) or [SEQUENCE RESTRICTION] (banned character sequence).
While building my clickies it caught "catches", "gradient" and "Herald", and a lot more. Here's what I know is banned, from the manual, Kaya's 2013 tests and errors I've hit in game:
script, extend, val, split, parse, open, mod, ini, ext, try, error, call, load, read, INF, is_a, T_AS, T_SR, E_PARSE, sprintf, key_exists, rename, catch, object, gradient, era, new, use, pass, stat, move, sid, die, true, and three dots in a row (...).
Also not allowed: $ variables, $_POST, var_dump.
Then there's my cautious list. Some are known PHP danger words and some have caused me trouble. I haven't confirmed every one of them is actually banned, but I avoid them all to be safe:
http, text, value, empty, null, break, save, session, var, safe, file, exit, global, function, include, require, eval, exec, system, shell, class, static, header, cookie, server, request, onclick, onload, javascript, iframe, alert, document, window, import, join, link, and __.
The fix is to split the word with . (which joins two strings):
echo "ex" . "tend"; @vv = 'va' . 'lue'; @vg = "linear-gra" . "di" . "ent(";
For three dots, put spaces between them: . . .
These are the everyday words that tripped me up, what's hiding in them, and what I did instead:
- valid, invalid, value (val): 'va' . 'lid'
- gradient (gradient, die): "linear-gra" . "di" . "ent("
- Herald, Seraph, Hourglass Seraph (era): 'Her' . 'ald'
- already, ready, spread, Stonetread (read): 'Stonetre' . 'ad'
- next (ext): reword it ("the day rolls over in")
- shining (ini): reword
- stately, status (stat): reword
- catches (catch): reword
- entry, Try (try): reword
- remove (move): reword
- side (sid): reword
- compass, password (pass): reword
- used (use): reword
- moderation (mod): reword (I went with "warden")
- object-fit in CSS (object): 'obj' . 'ect-fit'
- justify-content in CSS (content): avoid it
- description in uv (script): 'descri' . 'ption'
- a true argument (true): pass 1 instead
- array_values (val): loop over the array instead
- is_array (is_a): use is_scalar
- next(), str_split, preg_split (ext, split): not usable
- page load, new day (load, new): reword
Image file names and CSS count too. A picture called "mirrorseraph.gif" will trip "era".
The Functions You Can Use
-------------------------
MD Functions
- mds_has_rpcq_keys('a,b'): True if the player has ALL the keys.
- mds_give_rpcq_keys('a,b'): Gives the keys.
- mds_take_rpcq_keys('a,b'): Takes the keys.
- uv('name') (also mds_read_uvars): Reads a player fact (see Reading the Player).
- mds_storage(name, type): Opens or creates storage; gives the index into @storage.
- mds_storage_load, add, read: Old storage names; load and read reportedly blocked, not 100% sure.
- mds_store_sessdata(value, box) / storetmp: Saves text (max 250) in session box 0 to 9.
- mds_retrieve_sessdata(@holder, box) / retrievetmp: Reads a session box into a variable.
- store(@v) / retrieve(@v): Simple keep and fetch across items.
- mds_template(template, data, return, columns, td_attributes): Fills [[name]] placeholders; a list of records gives a table.
- debug(@v, 'label'): Shows a coloured dump box (the manual's mds_debug)
- mds_no_warnings(): Hides MDScript warnings only.
- mds_has_item('name'): How many of an item the player has.
- mds_is_itc(code): Checks an item code (pass only the ITC...MDI part); id, uid, playername, name, creationdate, transferdate, tag, or false.
- mds_is_ctc(code): Checks a creature code (CTC...MDC part); id, uid, playername, cid, tokens, dateBorn, transfercount, tradevalue, customName, vitality, level, experience, battlesWon, age, or false.
- mds_creature_icon(id, attrs): Prints a creature picture (creature ID, not the code)
- mds_player_avatar(name, attrs): Prints an avatar; max 5 per script.
- mds_player_heat(): The player's active heat.
- mdsi_takeheat(amount): Moves heat from the player into the item; asking for more than they have takes all and keeps nothing.
- mdsi_item_heat(): ['current' => total, 'players' => [name => heat]].
- mds_location_visits(loc or 'current'): How many times the player has visited.
- mds_check_group_location(players, coords): How many of those players are online there.
- mds_current_weather(): E.g. "heavyrain", or false.
- mds_get_resource_count(): [resource => count].
mds_is_atc was only ever wished for on the forum. As far as I know it doesn't exist.
Allowed PHP Functions (210)
Mur's original list has 236. Kaya found that 26 of them fail because their names contain banned pieces, which leaves these 210:
- Arrays: array, array_change_key_case, array_chunk, array_combine, array_diff, array_diff_assoc, array_diff_key, array_fill, array_fill_keys, array_flip, array_intersect, array_intersect_key, array_keys, array_merge, array_merge_recursive, array_multisort, array_pad, array_pop, array_product, array_push, array_rand, array_replace, array_replace_recursive, array_reverse, array_search, array_shift, array_slice, array_splice, array_sum, array_unique, array_unshift, arsort, asort, count, current, each, end, in_array, key, krsort, ksort, list, natcasesort, natsort, pos, prev, range, reset, rsort, shuffle, sizeof, sort, uasort
- Text: base64_decode, base64_encode, chop, chr, count_chars, crc32, crypt, echo, explode, get_html_translation_table, hash, htmlspecialchars, htmlspecialchars_decode, implode, lcfirst, md5, number_format, ord, print, printf, serialize, str_ireplace, str_pad, str_repeat, str_replace, str_rot13, str_shuffle, str_word_count, strcasecmp, strchr, strcmp, strcspn, strip_tags, stripos, stripslashes, stristr, strlen, strnatcasecmp, strnatcmp, strncasecmp, strncmp, strpbrk, strpos, strrchr, strrev, strrpos, strspn, strstr, strtok, strtolower, strtoupper, strtr, substr, substr_compare, substr_count, substr_replace, trim, ucfirst, ucwords, unserialize, url, urldecode, urlencode, vprintf, wordwrap
- Dates and times: date, date_add, date_create, date_diff, date_format, date_offset_get, date_sub, date_sunrise, date_sunset, date_timestamp_get, date_timezone_get, getdate, gettimeofday, gmdate, gmmktime, gmstrftime, idate, localtime, microtime, mktime, strftime, strptime, strtotime, time, timezone_location_get, timezone_name_get, timezone_offset_get, timezone_transitions_get
- Patterns: preg_filter, preg_match, preg_match_all, preg_quote, preg_replace
- Type checks: is_binary, is_bool, is_double, is_float, is_int, is_integer, is_nan, is_null, is_numeric, is_scalar, is_string, isset, unset
- Maths and other: abs, acos, acosh, asin, asinh, atan, atan2, atanh, base_convert, bindec, ceil, cos, cosh, decbin, dechex, decoct, deg2rad, exp, expm1, floor, getrandmax, hexdec, hypot, log, log10, log1p, max, min, mt_getrandmax, mt_rand, octdec, pi, pow, rad2deg, rand, round, sin, sinh, sqrt, srand, tan, tanh
- Old encryption: mcrypt_cbc, mcrypt_cfb, mcrypt_ecb, mcrypt_ofb
url is on the list but isn't a real PHP function. The basic language pieces like if, else, elseif, for, foreach, isset, array, list, echo and print all work.
These are on the list but don't work: array_count_values, array_intersect_assoc, array_values, chunk_split, date_interval_format, date_modify, date_parse, date_sun_info, fmod, the three geoip_ functions, is_array, is_finite, is_infinite, lcg_value, mt_srand, next, preg_last_error, preg_replace_callback, preg_split, similar_text, str_split, timezone_open, vfprintf, vsprintf. Also array_key_exists (removed) and var_dump (disabled).
Anything not on the list (for example ctype_digit) gives you a [LANGUAGE RESTRICTION].
Limits, Tips and Testing
------------------------
The limits I know of: 12 locations per script, 10 session boxes of 250 characters, and 5 mds_player_avatar calls per script. A member mentioned about 5 seconds of run time and a memory cap, but I haven't seen that confirmed officially. There's no official figure for maximum script size or storage size.
To find bugs, print values: print "V=" . @va; or debug(@va, 'va');. If a fatal error breaks the page, a blue "edit in case of error" link lets you fix it.
Design for the popup. The live clicky window is small, about 535 px wide and 165 px tall before it scrolls.
Build everything server-side with buttons. Each click is a fresh run, so keep state in storage or keys.
Know the staff rules. Don't copy or improve game or MD Shop features, no chats or messaging, don't show pictures of places players can't reach, "alternate reality" items need 70+ active days, and there's zero tolerance for abusive or tricking scripts. And never send players to the wrong internal page; staff warn that can get you banned.
If you have PHP on your computer, you can check grammar like a missing ; or unmatched brackets. Remove the (locations ...) line, change every @ to $, add <?php at the top, then run php -l. Line numbers will be off by one. It only catches syntax, though. It won't catch banned words, banned functions or wrong variable names, so search your script for the words above too. The real test is save&compile and then clicking it as a visitor.
The Official Docs
-----------------
- MD Script Manual (forum section): https://forum.magicduel.com/forum/168-md-script-manual/
- Step-by-step introduction for absolute beginners: https://forum.magicduel.com/topic/16837-a-step-by-step-introduction-to-mdscript-for-absolute-beginners/
- Variables: https://forum.magicduel.com/topic/5494-variables/
- Location setting: https://forum.magicduel.com/topic/6799-location-setting/
- Content sections: https://forum.magicduel.com/topic/5495-managing-content-sections/
- Storing values: https://forum.magicduel.com/topic/5492-how-to-store-valuesvariables-using-mdscript/
- Key control: https://forum.magicduel.com/topic/5498-key-control/
- User variables: https://forum.magicduel.com/topic/5499-user-variables/
- Restrictions and errors: https://forum.magicduel.com/topic/5493-restrictions-and-errors/
- PHP functions available: https://forum.magicduel.com/topic/5500-php-functions-availble-in-mdscript/
- Templates: https://forum.magicduel.com/topic/5496-templates/
- Debugging: https://forum.magicduel.com/topic/5497-debugging-your-code/
- Index of basic functions: https://forum.magicduel.com/topic/14268-index-of-basic-mdscript-functions-links/
- Content rules: https://forum.magicduel.com/topic/7137-new-rules-regarding-md-script-and-item-customizations/
Skip the "Old MD Script Language Reference". It's out of date.
Happy scripting, and if you build something, show me!
Seigheart
-
Invie got a reaction from Seigheart in The Cartographer's Cipher306-456-2-A972C7DB
-
Invie got a reaction from Seigheart in The Cartographer's Cipher305-244-1-04C140E3
-
Invie got a reaction from Seigheart in The Cartographer's Cipher303-0-0-73E74BCD
-
Invie got a reaction from Seigheart in The Cartographer's Cipher302-797-2-9BF0F675
-
Invie got a reaction from Seigheart in The Cartographer's Cipher301-464-1-917CA47D
-
Invie got a reaction from Seigheart in The Cartographer's Cipher299-990-1-98C9F7EE
-
Invie got a reaction from Seigheart in The Cartographer's CipherInvie 295-409-1-5335C75B
-
Invie got a reaction from Seigheart in The Cartographer's CipherInvie 294-0-0-8C33B622
-
Invie got a reaction from Seigheart in The Cartographer's CipherF2C742
-
Invie got a reaction from Seigheart in The Cartographer's CipherInvie 291-556-1-BC624571
-
Invie got a reaction from Seigheart in The Cartographer's CipherInvie 292-785-2-F86CF066
-
Invie got a reaction from Seigheart in The Cartographer's CipherInvie 293-1170-3-9AE5285A
-
Invie got a reaction from Blackshade Rider in Backgammon TournamentCount me in.
-
Invie got a reaction from Seigheart in The Cartographer's CipherThanks for the game, Seigheart.
It's a fun cipher, definitely worth trying.
-
Invie got a reaction from Seigheart in The Cartographer's CipherE68F5C
-
Invie reacted to Muratus del Mur in item mixing, more depthhere are my plans for recipes for a next depth of items.
The 'ingredients' are based on the most abundant items in the realm, sign that their use is either missing or not balanced.
Creating these items will consume existing items, and create more complex and functional items, or precursors to even more complex items.
I hope to be able to slowly create a path from resource, to more advanced items, and the most advanced items to be consumables requiring several levels of processing, with limited use but extreme power.
Your feedback is welcome and appreciated.
Functionality and actual mixing amounts are still open to debate.
IMPORTANT:
To avoid getting stuck in where to place the combiners and mixers for these items, i decided to create a central location for all this mixing. I don't have a place set yet, suggestions are welcome. Basically all mixing of next depth item such as these, will be do-able in one place. The next level after this (complexity 6-7), will be done in an other place, not the same.
====
COMPLEXITY LEVEL: 5-6
=====
Arcane Glass
Ingredients: Raw Glass + Reality Shards + Crystal
Description: By infusing raw glass with the mysterious properties of Reality Shards and finishing it with a crystalline sheen, you create a highly reflective, semi-sentient glass that warps light and confuses onlookers.
Function: ingredient for later mixing
Essence of Verdancy
Ingredients: Unidentified Plants + Aromatic Herbs + Flowers
Description: A small vial containing the concentrated essence of lush plant life. It smells of blossoming meadows and can be used in potent healing rituals or to magically enhance growth in gardens.
Function: ingredient for later mixing
Chrono Shard
Ingredients: Timeless Dust + Syntropic Dust + Memory Stone
Description: When you bind two time-altering substances (Timeless and Syntropic dust) around a fragment of Memory Stone, you craft a glowing shard that can momentarily slow or speed up time in the hands of a skilled mage.
Function: Maybe a fenths equivalent for the shattered apparition crit
Molten Golem Core
Ingredients: Rare Metals + Iron Ore + Golemus Dust
Description: These superheated metals, mixed with Golemus Dust’s potent magical essence, form a concentrated orb that acts as the “heart” of any construct or golem. It glows with an inner heat and radiates a low, rhythmic pulse.
Function: Ingredient for the currently non existant golem.
Corrupted Brew
Ingredients: Toxic Plants + Toxic Gas + Water
Description: A bubbling green mixture that reeks of danger. This poison-laced concoction is rumored to weaken even the mightiest creature if ingested—or, with proper alchemy, it could be refined into a powerful antidote, or a weapon.
Function: ingredient to build toxic bombs
Mudwood Bricks
Ingredients: Fine Sand + Clay + Water + Lumber
Description: Mixing damp sand and pliable clay, then reinforcing it with pulverized lumber fibers, yields a sturdy brick material. Dried in sunlight, these bricks are surprisingly strong and naturally resistant to erosion.
Function: part of future plans of allowing players to construct buildings, need to talk to chew about this
Soulbound Idol
Ingredients: Bones + Resin + Memory Stone
Description: A small, carved effigy formed from bleached bones, held together with resin and embedded with a Memory Stone shard. The idol can store fragments of the wearer’s essence, allowing for minor feats of necromancy.
Function: usable with necrotic ink for creating one time consumable against or in favor of clearly specified players.
Warding Effigy
Ingredients: Branches + Bushies + Rock Salt + Syntropic Dust
Description: Twisting branches into a humanoid form and lashing them together with Bushies for texture, you then coat the structure in Rock Salt and sprinkle it with Syntropic Dust. This scarecrow-like effigy deters low-level spirits from entering a guarded area.
Function: Defense are, +def spell effect of all online in same place. consumable.
Spirit Ink
Ingredients: Colored Paper + Ashes + Reality Shards
Description: Burn the colored paper to ashes, then imbue the powder with Reality Shards, creating an inky substance that shimmers with otherworldly patterns. Writing with Spirit Ink can manifest illusions or store magical seals within its text.
Function: usable with other items to get benefical results, similar to necrotic ink
Singing Clay
Ingredients: Clay + Resin + Timeless Dust
Description: Infusing malleable clay with Timeless Dust and sealing it with resin creates a soft, humming material. In the presence of active magic, it resonates with distant echoes, marking the flow of time with a steady hum.
Function: silvertongue casts, if mixed with memory stone
Lucid Candle
Ingredients: Aromatic Herbs + Resin + Syntropic Dust
Description: A “candle” formed by melting resin mixed with aromatic herbs, then sprinkled with Syntropic Dust. When lit, it produces a gentle, otherworldly glow that sharpens the mind and reveals hidden illusions or enchantments.
Function: reveal , cancel effect of any playername altering spells, stopping invisibility or impersonation. Probably should be mixed with heat jars or heat stones to be activated otherwise its too powerful.
Twilight Brew
Ingredients: Tea Leaves + Rainwater + Timeless Dust
Description: Steep freshly gathered tea leaves in pure rainwater, then swirl in a pinch of Timeless Dust. The resulting shimmering tea grants the drinker an extended twilight hour, delaying nightfall in their perception.
Function: Something related to night mode, maybe instant exit, or temporary exit (not sure if i can) from night mode.
Glistening Grimoire
Ingredients: Colored Paper + Gems + Memory Stone
Description: By binding lustrous gems onto colored paper lined with a fragment of Memory Stone, you craft a small book that can store illusions or recollections. Reading from its pages sometimes conjures faint, ghostly images of past events.
Function: either create a bestiary, now or with other items, or maybe create a stored collection of chats, like a capturing mechanism of chats in a location that will be kept forever in the item storage.
Toxic Bomb
Ingredients: Toxic Gas + Toxic Plants + Paper
Description: A volatile bundle of poison-laced flora and noxious fumes, wrapped tightly in paper. When ignited or ruptured, it spews a thick, toxic cloud, saturating the area with debilitating poisons.
Function: weapon, mass effect on all players online in same location, needs corrupted brew
Dustwalker Sandals
Ingredients: Fine Sand + Golemus Dust + Skin
Description: Compressing fine sand into a sturdy sole and bonding it with Golemus Dust between layers of treated skin yields footwear that leaves only swirling motes of dust behind. Wearers move silently across any terrain, as though half-ethereal.
Function: Consumable for action points
Whispering Stone
Ingredients: Stone + Memory Stone + Reality Shards
Description: A polished rock embedded with Memory Stone fragments and Reality Shards. When held, it whispers echoes of the past or half-forgotten secrets; tapping into it can reveal fleeting visions of lost knowledge.
Function: this could be very interesting, maybe future use, but for now it could be acoutsic remains spell stone.
Chrono Seeds
Ingredients: Unidentified Plants + Timeless Dust + Fenths
Description: By splicing strange seeds with a pinch of Timeless Dust and energizing them with Fenths, these peculiar plant seeds can sprout in different timelines. They sometimes produce bizarre “time-skipped” growths that show glimpses of alternate eras.
Function: Used as ingredient to switch path of creatures with branched futures, like snowman or angiens.
Arcane Filigree
Ingredients: Rare Metals + Gems + Reality Shards
Description: Intricate strands of rare metals are woven around brilliant gems, each thread imbued with tiny Reality Shards. Arcane Filigree is often set into staves or talismans to dramatically boost the power of illusions or elemental magic.
Function: Enhance other items
Wraith Lantern
Ingredients: Skull + Ashes + Resin
Description: Carved from a bleached skull and coated in hardened resin, the inside is filled with consecrated ashes that burn with an eerie, pale flame. When carried, it illuminates hidden paths and repels malevolent spirits.
Function: not sure
Bonsai Golem
Ingredients: Branches + Clay + Golemus Dust
Description: This tiny golem is formed from flexible branches anchored in malleable clay, animated by Golemus Dust. Its leafy sprigs grow at a slow pace, giving it the appearance of a living bonsai tree with a sentient core.
Function: used with fenths , and other, to obtain crit
Starmoss Essence
Ingredients: Aromatic Herbs + Mineral Water + Reality Shards
Description: A faintly glowing concoction created by steeping aromatic herbs in mineral water, then stirring in a sprinkle of Reality Shards. Starmoss Essence adds a celestial gleam to potions, rituals, or enchantments.
Function: not sure, beautifier of some sort
Bone Quill
Ingredients: Bones + Ashes + Colored Paper
Description: A slender bone is hollowed out for an ink reservoir, using ash to create a jet-black tip. This quill, when used on colored paper, can inscribe words that resonate with a faint necromantic power or store hidden messages.
Function: tool to write necrotic ink on personal item.
Animated Origami
Ingredients: Colored Paper + Sticky Goop + Syntropic Dust
Description: By folding intricate shapes from bright paper and bonding them with a drop of sticky goop, then dusting them lightly with Syntropic Dust, you can bring origami creatures to life. They flit about with a mischievous independence.
Function: next depth item, to be mixed with fenths and obtain fire elemental...ooorr.. usable as a portable creature totem reviver?
Memory Brew
Ingredients: Flowers + Tea Leaves + Memory Stone
Description: A delicate tea made by steeping fragrant blossoms with mild tea leaves and stirring in a ground fragment of Memory Stone. Drinking it can help recall forgotten details or solidify new memories.
Function: next depth item. Detach imprinted stones from their imprint, obtaining and ingredient to be used in exchange for one additional permanent cast of that spell.
Necrotic Ink
Ingredients: Toxic Plants + Bones + Ashes
Description: A pungent black ink brewed from crushed toxic plants, bone powder, and ash-laced water. Its necromantic traces can be used to scribe forbidden tomes or bind skeletal minions through ritual inscriptions.
Function: mix use with bone quill. to be combined with blood or autographs, in exchange of self curse but exponential power against set player,
-
Invie reacted to ignus_ in Why not Create a New Land, Blueberry of the DeadI'm thinking an entirely new country (as in factions in Md), full of colors and forest people. The navigation screens would be easy enough to draw... even if not, placeholders can be placed... i'm not saying make it something like one of those cheap (and strange) games with a jpg on every step.. just.. thinking adding some color to md.. Theme can be blueberries (and red) every where and the dead rising.. I nominate Lazarus and Aia as the leaders.. A new land would bring energy into game.. I can do the research/story if needed (for free). This new land can also
+ send new events to what is happening panel.. (ie dead is rising, their heart is heavy),
+ have new resources, mushroom/blueberries
+ have new everything.. if proper..
They must be a breakaway section of Necrovion.. i think. What do you say ?
Some ideas to run through :
Dead gates : (as entrance)
You sort of feel an undeniable pull, despite being fully aware there is only a dead end, and you'll be harmed
Blueberry Road
A busy road, that sees a lot of traffic. There are a lot of red
and blue fruits hanging from the heavy branches.. You can't
see the end of the blueberry forests..
Corn Maze Statue (as altar)
Beyond the end of the maze (perhaps how the geographically placed
as well), you see an altar of a rat among bunch of scattered and old statues. There are
some decorations on the wall, as you see start to see the environment
change from maze like to a proper city
Un dead Acorns (The sanctuary/base or maybe Shop, or Creature recruit), three areas perhaps
There is a hint of spell of constructs on the air, which is strange, since you'd think it'd
be shades and trees. This is an obscure and rare to place to encounter away
from the main lands. You see some fighters and some magic duels..
-
Invie reacted to jakubhi in Lost Knator Story(I decided to try to write a story for fun, I will be releasing some short parts of it in irregular intervals. Maybe more people will read it when it is not one long paragraph, hmm. The main idea of this story is to.. give certain areas in MD a bit of attention and life, I guess. I would be happy for any feedback. )
As a certain author once wrote:
„Scientists have calculated that the chances of something so patently absurd actually existing are millions to one.
But magicians have calculated that million-to-one chances crop up nine times out of ten. „
And so, a young knator ended up on a Gateway Island. It was unknown what took him away from the deep Loreroot forest, whether it was someone fooling around with spells or a hole in a reality.
But one thing was for sure. The knator did not have the slightest idea how to get back.
It was confused. And scared. It wanted to be home, in the forest, not.. whenever it currently was.
Looking around, the knator found only an empty beach, a tall cliff, and an ocean. Above the ocean, there was a storm. It was not moving left nor right. As if it was just.. floating there. And getting larger. And larger.
The young knator realised that he needed to find a place to hide. And fast.
PS: I thought knators had tails, but now that I am looking, I can't find any in the pictures
-
Invie reacted to Sunfire in Interrogation of WillowOn day 13 of the year 19 we have met Willow to interrogate him concerning the gifts that were found in his storage room.
Present at the time of the conversation were Invie and I, later joined by Ledah and Aamon, and Aia and Jakubhi when the meeting was running towards it end.
You can find the transcription below
TLDR
Willow is renting out his storage room to the confused one.
He spotted an elf returning gifts from the tree to the storage room, he confirmed it is the elf that had a shovel related incident that lead to his early passing
He doesn't know how the elven magic works that protects the gifts but might tinker a little with it.
He says our best bet to contact the confused one is to speak to the elves in the archives.
-
Invie reacted to Aia del Mana in Interrogation of WillowI fear I may be absent for this, but fortune may think otherwise.
1. Hast thou knowledge of any beings who did place the presents within the Willow's Shop storage? If so, what were the identity of them, and what were the appearance?
2. Knowst thou of any motive of such beings? Did they communicate in any manner to thee and if so, what spake them to thee? Were there a reason that the location for the presents were chosen, and what wer't?
3. Knowst thou of the magic that renders the presents inert, or a remedy that may dissipate of their inertia without also affecting their contents? If so, what wer't?
4. How art thou? Were there aught we may do for thee in return for thine aid in this matter?
5. When may one expect Willow's Shop to receive new items, for one who hath previously purchased of the entire inventory?
-
Invie got a reaction from Aia del Mana in An open letter to Confused Santa- Invie
-
Invie got a reaction from jakubhi in Library puzzleNice quest with a unique reward, I want even more of the reward.
-
Invie reacted to Chewett in Server Upgrade bugsThese issues should be fixed.
Please let me know if any persist.