PDA

View Full Version : SDK/Toolset. Game file format specifications.



Albeoris
08-22-2013, 07:48 PM
Hello!

One of the feature of the game - custom modifications (if believe the FAQ).
But while the potential modmakers no one has provided any tooling or descriptions game files to which they have to operate.

I understand that the main priority now is to develop a release version of the product. But many players and modmakers are waiting for support mods.

Therefore, please provide us with the tools to change the game. No matter how they are raw and unfinished (not for production). It is enough to these tools and instructions for setting up.

We already see that the game uses Unity3D, .NET via Mono.
And while it is not clear how to change resources, if they are packed in .assets-files.
We are also plagued by suspicions that the user interfaces are described in the code and can not be change.

At the moment, I and my colleagues have already matured some ideas for mods:

- Replace all interfaces gold coins on copper \ silver \ gold.
- Add a tab on the screen purchase equip to be able to sell things on a character, compare items, immediately buy and equip them.
- Add alternative methods of payment and receipt of money: Arkomage in taverns, dicing in forges, etc.
- In a few times to increase the duration of the day.
- Conduct a rebalancing of some enemies.
- Add new skills to the game (trade, disarm traps, repair).
- Add new spells in the game and the magic schools (body, spirit, mind). Strengthen the weak spells, diversify spells with similar effects, remove useless.

Nothing complicated, right? For Skyrim, Dragon Age, Shadowrun a lot of similar mods. I want to be sure that M&M X is no exception. And I want to start developing mods now, not after 4 years, after third addon.

Believe me, it is necessary not only to us (developers, players), but you (including the sales department), Rapidly emerging modifications - is maintaining a constant interest in the game between the releases of official addons.

P.S. Open Dev, yes? We're ready!...

Albeoris
08-22-2013, 09:22 PM
While answer is no, let's do research.

Static data - the characteristics of objects, monsters, spells, achievements, etc. are stored in the \ ... Data \ StreamingAssets \ StaticData.

They are serialized using CsvSerializer.dll. According to the model in C# you can see if load the library \ ... Data \ Managed \ Legacy.Core.dll (namespace Legacy.Core.StaticData). From here you can follow the chain of calls (ILSpy, ReSharper,. NET Reflector to help you), and to understand - how to use some data.

If anyone has any questions about the structure of a csv-file. Need lists of constants, or explanation of how they will be handled later, but you are not familiar with. NET and meet do not want to - ask, I will answer (in general, it is desirable to create a Wiki).

The primary objective: to realize the possibilities for dependency injection for incremental changes to existing functions without changing the original library. This will allow anyone to write on. NET plug-in, changing some parts of the engine and do not conflict with each other. Correct me if I'm wrong.

P.S. Dear developers, you've done a great gift for modders. Please do not obfuscate code.

Albeoris
08-22-2013, 09:48 PM
For example, let's take AchievementsStaticData.csv.
This file describes all the existing in-game achievements.

Titles:

StaticID, Icon, KeyName, DescriptionKey, ConditionID, Parameter, Counter, TriggerType, Global

Let us consider the first line:

1,, ACHIEVEMENT_HIRED_NAME, ACHIEVEMENT_HIRED_INFO, QUEST_COMPLETED, 5,0, QUEST_STEP_COMPLETED, FALSE

Open class

Legacy.Core.StaticData.AchievementStaticData

Among other things, we see the enum EAchievementConditionType, by which we can see all the available events, which can be linked to achieve.

QUEST_COMPLETED,
RELIC_ON_BOTH_ITEM_SLOTS,
ALL_CHARACTERS_ON_LEVEL,
PARTY_GOLD_AMOUNT_HIGHER_THAN_GOLD,
INGAME_DAYS_PASSED,
ALL_MEMBERS_UNLOCKED_ADVANCED_CLASS,
NUMBER_OF_LEARNED_SPELLS,
NUMBER_OF_UNIQUE_RELICS,
NUMBER_OF_ENTERED_TILES,
NUMBER_OF_REVIVINGS,
NUMBER_OF_INGAME_DAYS_SINCE_RESTING,
NUMBER_OF_BLOCKS,
NUMBER_OF_DEFEATED_MONSTERS,
NO_CHARACTER_DIED,
QUEST_COMPLETED_WITH_EXPLICIT_CLASS_IDS,
QUEST_COMPLETED_WITH_NO_DEATHS,
QUEST_COMPLETED_WITHOUT_CASTING_SPELL,
QUEST_COMPLETED_WITH_PARTY_OF_CLASSTYPE,

Look where it is used, we find constructor wrapper on that data:

public Achievement (AchievementManager p_manager, int p_staticID)
{
this.m_staticData = StaticDataHandler.GetStaticData <AchievementStaticData> (EDataType.ACHIEVEMENT, p_staticID);
this.m_manager = p_manager;
this.CreateCondition (this.m_staticData.ConditionID); / / Here's our ConditionID
}

Turning to the method:

internal void CreateCondition (EAchievementConditionType p_conditionType)

See the following case:

case EAchievementConditionType.QUEST_COMPLETED:
this.m_condition = (AchievementCondition) new QuestStepCompleteCondition (this, this.m_staticData.Count, this.m_staticData.ConditionParameter);
break;

Once inside, we see the logic of using of condition parameter:

public QuestStepCompleteCondition (Achievement p_achievement, int p_count, string p_parameterString)
: Base (p_achievement, p_count, p_parameterString)
{
}

public override void ParseParameter (string p_parameterString)
{
int.TryParse (p_parameterString, out this.m_questID);
}

public override bool CheckCondition (out int p_count)
{
p_count = 0;
QuestStep step = LegacyLogic.Instance.WorldManager.QuestHandler.Get Step (this.m_questID);
if (step == null | | step.QuestState! = EQuestState.SOLVED)
return false;
p_count = 1;
return true;
}

Thus, we found that for the event QUEST_COMPLETED parameter is the quest ID.
Of course, this could have guessed without reflect the code of the game. But now we know a few constants, which are yet to AchievementsStaticData.csv, and know - how to use them. The same goes for the rest of StaticData.

Albeoris
08-23-2013, 12:39 AM
Here is the first of the alleged modifications, which, as it turned out, lay in sight, but was only discovered after examining the source.

"Duration" days can be increased by 5-15 times or to make endless, switched only during rest (but note that this will affect the duration of some spells (in turns) and the damage per turn (in fact - for past time) damage venom regenration, etc.

The file \ ... Data\StreamingAssets\config.txt

Has options are:

minutesPerTurnOutdoor = 15
minutesPerTurnCity = 5
minutesPerTurnDungeon = 5
minutesPerRest = 480

You can edit them as you wish.

For myself, I put all the values ​​to 1 and the rest time increased to 10 hours.

P.S. Be careful - the file encoding ANSI, newline - \n (without \r). Edit the file with programs that do not kill the formatting.
P.P.S. Incidentally, the same file contains a lot of various factors that are, at times, thoroughly spoil life (for example, the chance of break item).

Albeoris
08-29-2013, 09:49 PM
One of the drawbacks of the game is a static range of shops.
But ... he is not quite static, but you can change it by adding more variability.

Over the range of shops is responsible table ItemOffers.csv (where it, see above)
Here is a schema that describes its structure and relationships to other tables:
http://i011.radikal.ru/1308/9a/daaf46e99ff3t.jpg (http://radikal.ru/fp/187d177a3e1d4fe79bbe416ba5745e13)

This way, you can:
- Add to the other dialogues merchant Offers.
- Add new offers, using Generated * for ItemEntries.
- Add a new Generated * items, with large sets of random types of objects, random levels.

The problem is solved.
Not only possible, indicate the chance that there will be offers. =\

AnjaBelle
08-30-2013, 06:08 PM
One of the drawbacks of the game is a static range of shops.
But ... he is not quite static, but you can change it by adding more variability.

Over the range of shops is responsible table ItemOffers.csv (where it, see above)
Here is a schema that describes its structure and relationships to other tables:
http://i011.radikal.ru/1308/9a/daaf46e99ff3t.jpg (http://radikal.ru/fp/187d177a3e1d4fe79bbe416ba5745e13)

This way, you can:
- Add to the other dialogues merchant Offers.
- Add new offers, using Generated * for ItemEntries.
- Add a new Generated * items, with large sets of random types of objects, random levels.

The problem is solved.
Not only possible, indicate the chance that there will be offers. =\

As I wrote here http://forums.ubi.com/showthread.php/790387-Randomness-of-shop-items?p=9252714&viewfull=1#post9252714 I failed to modify the file; there are no new items, it did nothing.
It was certainly my fault, because I'm sure I didn't understand your brief description.
Perhaps you could post a modified file as I wrote in the linked thread?

Albeoris
08-31-2013, 10:05 AM
As I wrote here http://forums.ubi.com/showthread.php/790387-Randomness-of-shop-items?p=9252714&viewfull=1#post9252714 I failed to modify the file; there are no new items, it did nothing.
It was certainly my fault, because I'm sure I didn't understand your brief description.
Perhaps you could post a modified file as I wrote in the linked thread?

Unfortunately, found that the code responsible for updating the assortment store does not work regardless of the settings file. Looking at the code, somewhere instead of предметов (or along with it) are deducted from the merchant offers. As a result, the items in the shop can not recover. Bug.

I asked support give us the sources of Legacy.* libs for modders - waiting for an answer. Otherwise will have to disassemble it yourself - it is easier to wait for the patch.

AnjaBelle
08-31-2013, 10:01 PM
Well, if I understood correctly, all the "modding" of said files is useless, right?

Perhaps you can answer one more question:

I fiddled around with Data\StreamingAssets\StaticData\ItemProbabilities:

# Item Probabilities,,
# Probabilities for item class/type/subtype for generated items,,
StaticID,Type,Probability
1,ARMOR,1
2,JEWELRY,0.05
3,SHIELD,1
4,MELEE_WEAPON,0.25
5,RANGED_WEAPON,0.1
6,MAGIC_FOCUS,0.05
7,HEADGEAR,1
8,GARMENT,1
9,GLOVE,1
10,BOOTS,1
11,NECKLACE,0.35
12,RING,0.65
13,SMALL_SHIELD,0.8
14,BIG_SHIELD,1
15,AXE,0.2
16,MACE,0.2
17,SWORD,0.2
18,DAGGER,0.2
19,SPEAR,0.2
20,BOW,0.5
21,CROSSBOW,0.5
22,MAGIC_FOCUS_ONEHANDED,0.8
23,MAGIC_FOCUS_TWOHANDED,0.2
24,CLOTHING,1
25,LIGHT_ARMOR,6
26,HEAVY_ARMOR,11
27,ARCANE,1
28,MARTIAL,1
29,ONEHANDED,0.8
30,TWOHANDED,0.2

As you can see, I changed some entries to "1", because I thought "1" is more than e.g. "0,25".
Then I created a new party and found lots of cloth-"armour" in the armourer shop. Also the chests in the spider cave and some chests outside town contained variations of this cloth-armour.
At least it provides the wearer with 3 AC, which is better than zero AC.

So, the altering of the entries actually DID something, however not really what I wanted. My goal was to have one basic armour for all my four guys (one heavy, two medium and one cloth).

Perhaps you can see, what I did wrong.

Albeoris
09-03-2013, 07:54 PM
Perhaps you can see, what I did wrong.

The values ​​in this table are responsible for the probability that a random item would be of some type.

When the subject appears on the shop counter, drops out of the chest or a monster, there are two sets of types:
1) Possible (bp two-handed sword, potion).
2) Preset (bp mail, sword, two-handed sword, potion, head monster, scroll)

If types intersect, then the type is selected at random from the intersection of these sets. The values ​​in the table are not affected.

And ONLY if no match, use data from this table.
1) Take a random number from 0 to 1.
2) Compare the chance to get the item of the first type.
3) If less - the type is defined.
4) If more - take the next type, the probability is added to the probability of the previous type.
5) Repeat until the end.

If all of the available types are over, but the random number is still greater than the sum of probabilities of all types, the game falls in error. :)

Possible sets (sum of the probabilities must equal 1):


private static readonly EEquipmentType[] EQUIPMENT_CLASSES = new EEquipmentType[]
{
EEquipmentType.ARMOR,
EEquipmentType.MELEE_WEAPON,
EEquipmentType.RANGED_WEAPON,
EEquipmentType.MAGIC_FOCUS,
EEquipmentType.JEWELRY,
EEquipmentType.SHIELD
};
private static readonly EEquipmentType[] ARMOR_TYPES = new EEquipmentType[]
{
EEquipmentType.GARMENT,
EEquipmentType.GLOVE,
EEquipmentType.BOOTS,
EEquipmentType.HEADGEAR
};
private static readonly EEquipmentType[] GARMENT_SUBTYPES = new EEquipmentType[]
{
EEquipmentType.CLOTHING,
EEquipmentType.LIGHT_ARMOR,
EEquipmentType.HEAVY_ARMOR
};
private static readonly EEquipmentType[] ARMOR_SUBTYPES = new EEquipmentType[]
{
EEquipmentType.ARCANE,
EEquipmentType.MARTIAL
};
private static readonly EEquipmentType[] MELEE_WEAPON_TYPES = new EEquipmentType[]
{
EEquipmentType.SWORD,
EEquipmentType.AXE,
EEquipmentType.MACE,
EEquipmentType.DAGGER,
EEquipmentType.SPEAR
};
private static readonly EEquipmentType[] MELEE_WEAPON_SUBTYPES = new EEquipmentType[]
{
EEquipmentType.ONEHANDED,
EEquipmentType.TWOHANDED
};
private static readonly EEquipmentType[] RANGED_WEAPON_TYPES = new EEquipmentType[]
{
EEquipmentType.BOW,
EEquipmentType.CROSSBOW
};
private static readonly EEquipmentType[] JEWELRY_TYPES = new EEquipmentType[]
{
EEquipmentType.NECKLACE,
EEquipmentType.RING
};
private static readonly EEquipmentType[] SHIELD_TYPES = new EEquipmentType[]
{
EEquipmentType.SMALL_SHIELD,
EEquipmentType.BIG_SHIELD
};
private static readonly EEquipmentType[] MAGIC_FOCUS_TYPES = new EEquipmentType[]
{
EEquipmentType.MAGIC_FOCUS_ONEHANDED,
EEquipmentType.MAGIC_FOCUS_TWOHANDED
};

If you want to random items GARMENT often drop HEAVY_ARMOR, you need to reduce the probability of CLOTHING and \ or LIGHT_ARMOR, and increase HEAVY_ARMOR.

Before:
24,CLOTHING,0.4
25,LIGHT_ARMOR,0.4
26,HEAVY_ARMOR,0.2
---
Sum: 1.0

After:
24,CLOTHING,0.1
25,LIGHT_ARMOR,0.1
26,HEAVY_ARMOR,0.8
---
Sum: 1.0