Monsters' Den: Godfall

Monsters' Den: Godfall

Not enough ratings
Intro to Modding Monster's Den: Godfall (Spoilers)
By Parabola01
This guide will explore how to mod your copy of Monster's Den: Godfall to add new equipment, skills, effects, enemies, and more.
2
   
Award
Favorite
Favorited
Unfavorite
Introduction
Before we get started, a few disclaimers:
  • Back up your game before you start and do so often as you work on it. It will save you the trouble of having to redownloading the game and starting from scratch if something goes wrong.
  • Any update will cause all your work to be undone. It's another reason to save often and make lots of copies. At worst, you could copy old code from one file into a newer one, saving some time.
  • I recommend finishing the campaign before trying to mod. You are going to see spoilers in the code and probably in this thread.
  • While modding your game, you are solely responsible for what happens to it.
  • This guide is a work in progress. If you have any suggestions, please let me know!

What you'll need:
  • The Godfall .swf
  • A text editor (I recommend Notepad++. It's free)
  • A flash decompiler (I reommend JPEXS. It is also free)

To begin with, find the Godfall .swf in JPEXS and "Export all parts" to a new folder. Put the folder someplace you can get to easily as you'll be working in there a decent amount.

Note about JPEXS:
JPEXS is the only unlimited free flash decompiler I could find. If anyone else finds one, let me know, because what we're using certainly isn't perfect. For one, the product is no longer being updated. Secondly, the "Edit ActionScript" option that has (Experimental) next to it simply doesn't work for us. Editting the code with that option will result with Godfall crashing on start up. Our only option in these cases is to use Edit P-Code.

In addition, I though support for JPEXS had died, but it turns out they have updated it somewhat recently. I have not used it, but I'll try it over the course of making this guide.
First Example: The Files
To start, though, we aren't going to go into the P-Code as it is a bit more complex. The good news is we can easily add new equipment to the game without touching it. We'll start by tracking down some files. My comments will look like this.

binaryData:
all files in binaryData have a 4 digit code in the front of the filename. That code isn't as important as the rest of the string. I won't be writing the code number to avoid confusion between game editions.
  • md2.items.ItemXML_artifactsFile.bin where all the artifacts are kept
  • md2.items.ItemXML_armorFile1.bin purple-tier armor sets
  • md2.items.ItemXML_armorFile2.bin teal-tier armor sets
  • md2.items.ItemXML_epicsFile.bin purple-tier weapons and armor
  • md2.items.EquipmentSet_setsXMLClass.bin equipment set bonuses
  • md2.items.ItemXML_factionRewardsFile.bin faction reward armor sets

scripts:
  • Stat.as all the item stats
  • Tag.as all the possible tags

scripts -> md2 -> items:
  • EquipmentSpecialEffect.as special effect triggers on equipment (when attacked, on crit, when healing, ect)
  • Item.as item rarities and base damage
  • ItemTypes.as equipment types

scripts -> md2 -> skills:
  • Effect.as all the game's buff and debuff effects
  • MonsterSkill.as the monster skills. Note that monsters follow a different damage algorithm, so you'd need to edit P-Code to use any damaging monster skills to their full potential. Skills may have unintended side-effects.
  • PassiveSkill.as the player's passive skills
  • Skill.as the player's skills
  • SkillTree.as the player's skill trees
First Example: The Code
Let's start with an example artifact, and one of my personal favories: Nature's Bargin.
<equipment name="Nature's Bargain" type="15" id="4950" rarity="9" baseMultiplier="2.2" setId="0" backer="Alex" slots="2"> <appearance icon="12" model="19" glowAlpha="0" glowColor="0"/> <usableBy default="false"> <requires tree="14"/> </usableBy> <lore text="Life cannot exist without death, and through death all that exists must end. "/> <effect chance="100" targetSelf="false" disintegrate="false" disintegrateTag="0" action="0" health="0" power="0" remove="0" trigger="6" effectId="116"/> <stat id="19" value="15" type="fixed"/> <stat id="55" value="50" type="fixed"/> <stat id="4" value="30" type="fixed"/> <stat id="4" value="3" type="tier"/> <stat id="80" value="282" type="fixed"/> <stat id="1040" value="100" type="fixed"/> <stat id="1040" value="25" type="relic"/> <stat id="36" value="1" type="fixed"/> <stat id="102" value="20" type="fixed"/> </equipment>
Let's break this down point by point:

Equipment Tag
  • <equipment>: the starting and closing tags tell the game that this is an equipment
  • name: the equipment name as it appears in game
  • type: the item base type. Use ItemTypes.as and find the constant that matches the number. In this case, we have 15 which is STAFF.
  • id: the unique item ID. Make sure every item you add has a unique ID or they'll start overwritting each other.
  • rarity: the item rarity. Use Item.as and look up the number. In this case, a 9 leads to RARITY_ARTIFACT.
  • baseMultiplier: how much the base damage/armor is multiplied by. Check Item.as for weapon base damage.
  • setId: if the weapon is a part of a set, this won't be a 0. In that case, see md2.items.EquipmentSet_setsXMLClass.bin for the set effects.
  • backer: name of the backer that the weapon was made after. This causes that green dot on the item card in game
  • slots: enchantment slots available.
Appearance Tag
  • <appearance>: the starting and closing tags that govern how the item looks
  • icon: the item icon
  • model: the item model when equipped to a character
  • There are more tags as well, including glows hue changes and more. I haven't tracked down where all these come from, so I mostly copy and paste the looks from other items. It's mostly trial and error for me.
UseableBy Tag
  • <usableBy>: start and close tags that deal with what classes can use the item
  • default: can be "true" or "false". If "true" the standard classes that can equip that base type are able to use it. If false, any class can use it.
  • requires tree: allows a tree to use the item. See SkillTree.as for what number means what. In this case, we have 14. That's RANGER_NATURE.
  • restricted tree: restricts a tree from using the item. It's not shown in our example.
Lore Text Tag
  • <lore text>: The lore text!
Effect Tag
  • <effect>: The effect tag. This will govern what special properties the item has.
  • chance: %chance of the effect triggering.
  • targetSelf: if "true", the effect applies to the equipment wearer. If "false", the effect applies to the target.
  • disintegrate: "true" or "false" if the effect causes disintegration
  • disintegrateTag: check Tag.as for available tags. Any tag here will disintegrate enemies with that tag. If "0", no tag is used.
  • action: action gained (positive number) or lost (negative number). 3000 = 1 full action circle.
  • health: HP gained (positive number) or lost (negative number). This value will scale with item tier.
  • power: Power gained (positive number) or lost (negative number). Does not scale with tier.
  • remove: removes an amount of debuffs (if targeting party) or buffs (if targeting an enemy)
  • trigger: how the effect activates. Use EquipmentSpecialEffect.as. In this case, we have a 6 which leads to TRIGGER_WHEN_HEALING.
  • effectId: if not a 0, it will apply an Effect. Check Effect.as and find the constant that matches the number. 116 equals EF_RANGER_THORNS.
Stat Tag
  • <stat>: A stat for the item.
  • id: The kind of stat being applied. Check Stat.as for possible options.
  • value: the amount
  • type: three choices here. "fixed" gives a static value that does not change. "tier" adds the value amount that much per item tier (or 1/3 the value per level), and "relic" is a relic effect.
Special Stat ids:
  • stat id="80": This adds a skill to the item. MonsterSkill.as, PassiveSkill.as, and Skill.as are all available to use.
  • stat id="1000+": If the id number is more than 1000, the stat is for a resistance. Subtract 1000 from the id and look up the remainder in Tag.as.
First Example: Equipment
Inserting an equipment into the game is actually pretty easy:

  1. Open the .bin file of your choice from the first post in a text editor.
  2. Make any changes to it that you desire and save the file.
  3. Right-click on the same file name within the .swf tree (in binaryData) in JPEXS and Replace it with the one you just edited.
  4. The file in the tree will turn bold to let you know that it has been changed.
  5. Save.
  6. Open Godfall and see what happens!

Here's a few examples of what I've made in the past using these exact steps:

4th Emporium Tab: Debug Shop
Before unlocking the 4th Emporium tab, I highly recommend making a copy of the .swf file. We're going to need to go into the P-Code and if the P-Code gets screwed up, it carries a risk of crashing the game. What I've done has been perfectly stable, though.

In JPEXS, navigate to:
scripts -> md2 -> shop -> Shop

Find the following block of text and click somewhere in it:
case EMPORIUM: this.name = "The Emporium"; this.bagIds.push(ShopInventoryBags.EMPORIUM_SPECIAL); this.bagIds.push(ShopInventoryBags.EMPORIUM_ACCESSORIES); this.bagIds.push(ShopInventoryBags.EMPORIUM_CONSUMABLES); if(Main.isDebugVersion) { this.bagIds.push(ShopInventoryBags.DEBUG_ARTIFACTS); } this.allowsBribeForRestock = false; break;
This will move the P-Code window to the needed area:
pushstring "The Emporium" initproperty Qname(PackageNamespace(""),"name") getlocal_0 getproperty Qname(PackageNamespace(""),"bagIds") getlex Qname(PackageNamespace("md2.shop"),"ShopInventoryBags") getproperty Qname(PackageNamespace(""),"EMPORIUM_SPECIAL") callpropvoid Qname(Namespace("http://adobe.com/AS3/2006/builtin"),"push") 1 getlocal_0 getproperty Qname(PackageNamespace(""),"bagIds") getlex Qname(PackageNamespace("md2.shop"),"ShopInventoryBags") getproperty Qname(PackageNamespace(""),"EMPORIUM_ACCESSORIES") callpropvoid Qname(Namespace("http://adobe.com/AS3/2006/builtin"),"push") 1 getlocal_0 getproperty Qname(PackageNamespace(""),"bagIds") getlex Qname(PackageNamespace("md2.shop"),"ShopInventoryBags") getproperty Qname(PackageNamespace(""),"EMPORIUM_CONSUMABLES") callpropvoid Qname(Namespace("http://adobe.com/AS3/2006/builtin"),"push") 1 getlex Qname(PackageNamespace(""),"Main") getproperty Qname(PackageNamespace(""),"isDebugVersion") iffalse ofs00f1 getlocal_0 getproperty Qname(PackageNamespace(""),"bagIds") getlex Qname(PackageNamespace("md2.shop"),"ShopInventoryBags") getproperty Qname(PackageNamespace(""),"DEBUG_ARTIFACTS") callpropvoid Qname(Namespace("http://adobe.com/AS3/2006/builtin"),"push") 1 ofs00f1:getlocal_0 pushfalse initproperty Qname(PackageNamespace(""),"allowsBribeForRestock") jump ofs02c3
Click Edit P-Code and remove the following lines:
getlex Qname(PackageNamespace(""),"Main") getproperty Qname(PackageNamespace(""),"isDebugVersion") iffalse ofs00f1
And on the following line, remove ofs00f1:
ofs00f1:getlocal_0
Save the P-Code and then Save the file. Then give the Emporium a visit next time you're in the game! Here's an example which includes some custom Artifacts I've made:
Enabling Restocks
For enabling restocks in shops, we'll be looking in scripts > md2 > shop > Shop. Let's look at some example code:
case KEEP_QUARTERMASTER: this.name = "Quartermaster"; this.bagIds = [ShopInventoryBags.QUARTERMASTER_SPECIAL]; this.allowsBribeForRestock = false; break;
Our goal is to change that 'false' to a 'true'. Let's enter the equivalent P-Code to see how to do that:
ofs006a:label getlocal_0 pushstring "Quartermaster" initproperty Qname(PackageNamespace(""),"name") getlocal_0 getlex Qname(PackageNamespace("md2.shop"),"ShopInventoryBags") getproperty Qname(PackageNamespace(""),"QUARTERMASTER_SPECIAL") newarray 1 initproperty Qname(PackageNamespace(""),"bagIds") getlocal_0 pushfalse initproperty Qname(PackageNamespace(""),"allowsBribeForRestock") jump ofs02c3
See that line towards the bottom that says 'pushfalse'? All you need to do is change it to 'pushtrue'! Conversely, if you want to disable a restock option, you would change a 'pushtrue' to a 'pushfalse'.
Increasing Item Stock
Increasing item stock in the shops is more of a case-by-case basis. If you have a specific example in mind, I'd be happy to go through it, but until then I'll give a few pointers. We'll be doing our coding in scripts > md2 > shop > ShopInventoryBags.

If the Item is in a Loop:
Let's start with an example where the item exists within a loop:
case EMPORIUM_SPECIAL: ItemGenerator.setRarityTable(RarityTable.SHOP_GENERIC,1,true,false); _loc4_ = 0; while(_loc4_ < 3) { _loc2_.push(ItemGenerator.getRandomSkillManual(_loc10_)); _loc4_++; } _loc4_ = 0; while(_loc4_ < 1) { _loc2_.push(Items.getItem(Items.SCRAP_OF_ARTIFACT_LORE,1)); _loc4_++; } _loc4_ = 0; while(_loc4_ < 5) { _loc2_.push(ItemGenerator.getRandomReputationItem(1,Faction.PRIVATE_CITIZENS,false,_loc10_)); _loc4_++; } if(ref.company && ref.company.campaignSideQuestsCompleted.indexOf(CampaignQuests.NEKOATL) != -1) { _loc2_.push(Items.getItem(Items.RELIC_NEKOATL_RELIC,1)); } break;
Let's say we want more Scraps of Artifact Lore. _loc4_ is 0 entering the loop, and the loop is executed as long as it is less than 1. In this case, it only runs once, generating one Scrap. Let's change that.

Start by clicking just before the 1 inside this bit of code:
while(_loc4_ < 1)
This should highlight the following bit of P-Code:
pushbyte 1
These 1s are one in the same! If you change the "pushbyte 1" to say, "pushbyte 2" then 2 Scraps will spawn every month. If you put in a larger number, however, you need to use "pushshort". JPEXS should promt a warning message for this.

Here's an example of what happens in game after changing it to around 60:


If the Item is Not in a Loop:
This is more annoying to change. It's not difficult, though. You could make your own while-loop to stick the item into, like I showed above, but I tend to shy away from that unless I plan on changing that number a lot. Let's look at another example:
if(_loc6_ >= Reputation.REPUTATION_LEVEL_REQUIRED_FOR_CONSUMABLE_UNLOCK) { _loc14_ = Reputation.getConsumableIdUnlockedByFaction(_loc13_); addItemToVectorById(_loc2_,_loc14_,1); if(_loc14_ != Items.LEGENDARY_LAIR_MAP) { addItemToVectorById(_loc2_,_loc14_,1); } if(_loc14_ == Items.SHRINE_CLEANSING_OIL || _loc14_ == Items.SCROLL_AMBUSHES) { addItemToVectorById(_loc2_,_loc14_,1); } }
This bit of code is giving the factions shops their consumables. Specifically, the bit
addItemToVectorById(_loc2_,_loc14_,1);
is what is adding the item. So what if we want more in the shop? It's just simple copy and paste! Let's look at the appropriate P-Code:
findpropstrict Qname(PrivateNamespace(null,"294"),"addItemToVectorById") getlocal_2 getlocal 14 pushbyte 1 callpropvoid Qname(PrivateNamespace(null,"294"),"addItemToVectorById") 3
So, all you do is copy and paste that code! so if we want to start with a base of two items, our P-Code would look like:
findpropstrict Qname(PrivateNamespace(null,"294"),"addItemToVectorById") getlocal_2 getlocal 14 pushbyte 1 callpropvoid Qname(PrivateNamespace(null,"294"),"addItemToVectorById") 3 findpropstrict Qname(PrivateNamespace(null,"294"),"addItemToVectorById") getlocal_2 getlocal 14 pushbyte 1 callpropvoid Qname(PrivateNamespace(null,"294"),"addItemToVectorById") 3
And the ActionScript turn into:
addItemToVectorById(_loc2_,_loc14_,1); addItemToVectorById(_loc2_,_loc14_,1);
You can repeat this multiple times and it would look like this:
Custom Effect Example: Static Field
For this example, we're going to create the following effect from this equipment:
While an effect exists in the game much like this one, there isn't an effect *exactly* like it. For that reason, we're going to need to make it ourselves. And that involves a few steps. We'll be working out of scripts -> md2 -> skills -> Effect

Step 1: The Effect Code
The code itself for this skill doesn't look too bad:
ofs5e6c:label getlocal_0 pushstring "Static Field" initproperty Qname(PackageNamespace(""),"effectName") getlocal_0 getlex Qname(PackageNamespace(""),"Tag") getproperty Qname(PackageNamespace(""),"LIGHTNING") getlex Qname(PackageNamespace(""),"Tag") getproperty Qname(PackageNamespace(""),"MAGIC") getlex Qname(PackageNamespace(""),"Tag") getproperty Qname(PackageNamespace(""),"TOOL") newarray 3 initproperty Qname(ProtectedNamespace("md2.skills:Effect"),"tags") getlocal_0 getproperty Qname(PackageNamespace(""),"statModifiers") getlex Qname(PackageNamespace(""),"Stat") getproperty Qname(PackageNamespace(""),"CAUSE_STUN") pushbyte 10 setproperty MultinameL([PrivateNamespace(null,"61"),PackageNamespace(""),PackageNamespace("md2.skills"),ProtectedNamespace("md2.skills:Effect"),PrivateNamespace(null,"431"),PackageInternalNs("md2.skills"),Namespace("http://adobe.com/AS3/2006/builtin"),StaticProtectedNs("md2.skills:Effect")]) getlocal_0 getproperty Qname(PackageNamespace(""),"statModifiers") getlex Qname(PackageNamespace(""),"Stat") getproperty Qname(PackageNamespace(""),"ADD_TAG_TO_SKILLS") getlex Qname(PackageNamespace(""),"Tag") getproperty Qname(PackageNamespace(""),"LIGHTNING") setproperty MultinameL([PrivateNamespace(null,"61"),PackageNamespace(""),PackageNamespace("md2.skills"),ProtectedNamespace("md2.skills:Effect"),PrivateNamespace(null,"431"),PackageInternalNs("md2.skills"),Namespace("http://adobe.com/AS3/2006/builtin"),StaticProtectedNs("md2.skills:Effect")]) getlocal_0 getlex Qname(PackageNamespace(""),"DURATION_LONG") initproperty Qname(PackageNamespace(""),"maxDuration") getlocal_0 getlex Qname(PackageNamespace(""),"ico_ef_lightning") initproperty Qname(PrivateNamespace(null,"61"),"_iconClass") jump ofs75d0
Note that the ofs hex numbers that work for me may not work for you. They seem to be changed when saving. What's more important is that the numbers you enter are unique from any others.

The ofs work as look-up values. So if another bit of P-Code is looking for ofs5e36, it will find Static Field effect. Otherwise, it will pass it by. I mention this because it's important to always use the exact same ofs label when you want one bit of code to find another. But that ofs pair must be different from all other ofs in the code, or else they'll come along for the ride as well. I'm hoping that makes sense.

The P-Code of the effects themselves are fairly straightforward and cobbled together from other effects already in the file. The duration (DURATION_LONG) is defined near the top of the Effect file as four turns.

Step 2: The Lookup Table
Next we need to append the effect to the lookup table, located near the end of the P-Code:
ofs7247:getlex Qname(PackageNamespace(""),"EF_EXECUTOR_ASPECT_THYSION") getlocal 9 ifstrictne ofs7257 pushshort 316 jump ofs7276 ofs7257:getlex Qname(PackageNamespace(""),"EF_ITEM_STATIC_FIELD") getlocal 9 ifstrictne ofs7268 pushshort 317 jump ofs7276 ofs7268:jump ofs7273 pushshort 318 jump ofs7273 ofs7273:pushshort 318 ofs7276:kill 9 lookupswitch ofs5ec3 318 ofs0075 ofs00aa ofs00e6 ofs0132 ofs017e ofs01d2 ofs0211 ofs027a ofs02c6 ofs0304 ofs035b ofs03a6 ofs03dd ofs042e ofs0485 ofs04c7 ofs04f6 ofs0538 ofs0572 ofs05cc ofs069b ofs06dc ofs0709 ofs0751 ofs07b3 ofs0805 ofs084e ofs087e ofs08d9 ofs0908 ofs093d ofs0978 ofs09c7 ofs0a0e ofs0a55 ofs0aac ofs0b13 ofs0b46 ofs0bbf ofs0c29 ofs0c92 ofs0ce9 ofs0d3f ofs0d90 ofs0e03 ofs0e6d ofs0ec7 ofs0f21 ofs0f68 ofs0fd3 ofs100c ofs1064 ofs10f8 ofs114b ofs1187 ofs11d3 ofs120b ofs1252 ofs12b7 ofs12ef ofs1327 ofs1363 ofs13af ofs1407 ofs147c ofs14e4 ofs1566 ofs15bf ofs15f5 ofs163b ofs166c ofs16be ofs1701 ofs1754 ofs1795 ofs17e3 ofs17ff ofs183b ofs18d6 ofs190d ofs194a ofs1981 ofs19d4 ofs1a73 ofs1ad7 ofs1b40 ofs1b92 ofs1be1 ofs1c4f ofs1c8b ofs1d49 ofs1d9d ofs1dd2 ofs1df3 ofs1e14 ofs1e39 ofs1e6b ofs1e8c ofs1eb1 ofs1ed6 ofs1eec ofs1f28 ofs1f66 ofs1f99 ofs1fd9 ofs2043 ofs207e ofs20c4 ofs2110 ofs215b ofs21cf ofs2255 ofs22a4 ofs22eb ofs233d ofs237d ofs239c ofs23e2 ofs2433 ofs2484 ofs24d5 ofs2519 ofs2564 ofs25af ofs2603 ofs2639 ofs266f ofs26b0 ofs275a ofs2804 ofs28ae ofs294a ofs2986 ofs29b7 ofs29cd ofs29f6 ofs2a38 ofs2a59 ofs2a7a ofs2ac1 ofs2af9 ofs2b41 ofs2b7d ofs2bb4 ofs2be0 ofs2c05 ofs2c47 ofs2c58 ofs2c7e ofs2cdf ofs2d04 ofs2d29 ofs2d4e ofs2d83 ofs2da4 ofs2ded ofs2e22 ofs2e57 ofs2e97 ofs2ec8 ofs2f0b ofs2f42 ofs2f79 ofs2fb0 ofs2ff2 ofs3054 ofs3096 ofs30d9 ofs318e ofs31ca ofs321c ofs327e ofs32ca ofs3301 ofs3338 ofs336f ofs33a6 ofs3400 ofs3437 ofs346a ofs34a1 ofs34d8 ofs350f ofs3546 ofs3582 ofs35e9 ofs3625 ofs367c ofs36c8 ofs370f ofs3751 ofs37ab ofs3829 ofs388c ofs38c8 ofs3904 ofs393b ofs3992 ofs39c9 ofs3a00 ofs3a51 ofs3a8a ofs3adf ofs3b34 ofs3b89 ofs3bc0 ofs3c07 ofs3c6e ofs3cab ofs3ce8 ofs3d25 ofs3d7c ofs3dbb ofs3e35 ofs3e6c ofs3ea3 ofs3f00 ofs3f49 ofs3f9c ofs3fea ofs404b ofs40a2 ofs40f4 ofs414a ofs41a7 ofs41eb ofs425c ofs42d1 ofs432a ofs438c ofs43e9 ofs446f ofs44d2 ofs454c ofs45b9 ofs45f5 ofs4651 ofs469d ofs46fa ofs4731 ofs4767 ofs47bb ofs47f2 ofs4821 ofs486d ofs48ba ofs4906 ofs494c ofs4999 ofs49ea ofs4a3b ofs4a77 ofs4abd ofs4af3 ofs4b43 ofs4b8a ofs4bcc ofs4c2f ofs4c8d ofs4cc4 ofs4d0b ofs4d59 ofs4db7 ofs4e03 ofs4e60 ofs4ea2 ofs4ef1 ofs4f3e ofs4f7a ofs4fc8 ofs5021 ofs5068 ofs5095 ofs50cc ofs5108 ofs514f ofs519c ofs522b ofs527a ofs52cf ofs5319 ofs5363 ofs53a6 ofs53f9 ofs545e ofs54b1 ofs5504 ofs5557 ofs55c0 ofs5614 ofs56a2 ofs56e0 ofs571e ofs575c ofs5794 ofs57da ofs5811 ofs5858 ofs58a3 ofs58f9 ofs5931 ofs5983 ofs59d1 ofs5a20 ofs5a58 ofs5a90 ofs5aef ofs5b0f ofs5b69 ofs5bc3 ofs5c1d ofs5c77 ofs5d11 ofs5d6b ofs5dc4 ofs5dfc ofs5e34 ofs5e6c ofs5ec3
I'd go into more detail, but I'm hitting a text limit for this section. Here's the jist of it:
  1. With 317 effects in the vanillia version, we're adding another. So anwhere you see 317 in this area of the code, add one to make it 318
  2. Enter a new section after the last skill effect (Aspect of Thysion)
  3. The new effect's jump ofs should be what Aspect of Thysion's is
  4. Change the ofs on the jump for Aspect of Thysion to be the same as the new effect's ofs
  5. Put the ofs label from Step 1 as the second-to-the-last value in the lookup table

Step 3: The Public Static Constant
Finally, we need to add a public static constant to the code. To do this:
  • Click on the button Add Trait directly above the ActionScript window.
  • Check the Static box.
  • Make sure the dropdowns are as public and Const
  • Name the constant (EF_ITEM_STATIC_FIELD for this example)
Then click in the ActionScript to take you to the P-Code:
trait const Qname(PackageNamespace(""),"EF_ITEM_STATIC_FIELD") slotid 312 type Qname(PackageNamespace(""),"int") value Integer(811) end ; trait
Here, only two items have been changed:
  • The slotid needs to be unique. The highest number in vanilia is 311, so we'll start with 312.
  • The integer value needs to correspond with the effect ID. 811 is an unused ID in vanilia, so we can use it.
Custom Skill Example: Tremor
Here's an example of a custom skill I made. I'll go over my thought process and how I arrived where I did.

Basically, I wanted some Earth Magic to cast with. During the quest where we fight elementals, there are 4 kinds (fire, lightning, ice, and earth) yet we can cast spells of all those elements *except* Earth. Naturally, looking at skills involving the ground had me thinking of applying Terrain effects with the skill. Now what isn't in the game is a skill or effect that applies a Terrain without first removing one, which is what I wanted. So, here's how the final skill ended up:
case SK_TREMOR: this.skillName = "Tremor"; this.rawDescription = "Send a tremor through the ground that disrupts the terrain underneath enemies. Deals |dmg|, removes all terrain conditions, and applies Loose Footing."; this.targetsAnyEnemy = true; this.hitsAllEnemies = true; this.destroysTerrain = true; this.applyLooseFooting = true; this.scaleType = SCALE_WITH_INTELLECT; this.scaleDamage = 0.4; this._notUsableOutsideCombat = true; this.actionType = ACTION_FULL; this._powerCost = 70; this.cooldownTotalTurns = 4; this.animUser = Anim.FX_GROUND_PULSE_OUT_YELLOW; this.soundEffectInitial = Sounds.HOLY_IMPACT; this.preHitFrames = 20; this.iconClass = ico_ef_crystals; this.aiCastLimit = 0; this._baseDamageType = Damage.PHYSICAL; this.skillTags = [Tag.SPELL,Tag.AREA_EFFECT,Tag.TERRAIN,Tag.PHYSICAL];
The code is basically a mash-up of Even the Odds and Lightning Storm with some number tweaks. One line I want to draw attention to is this one:
this.applyLooseFooting = true;
This variable didn't exist. I had to make it. That was the easy part.
public var applyLooseFooting:Boolean;
Now I had to tell the game what to do with this variable. This comes from the script SkillExecutor. I started by backtracking and looking at "this.destroysTerrain" and basing my code off that. That lead me to this bit of code:
if(this.skill.destroysTerrain && _loc25_) { this.destroyTerrainOnGrid(_loc25_.grid); }
So now I had to look up "destroyTerrainOnGrid" which happened to be in the same file:
private function destroyTerrainOnGrid(param1:BattleGridIndicator) : Boolean { if(param1 && param1.terrainTypeId) { param1.setTerrainModifier(Terrain.NONE); if(param1.charRef) { param1.charRef.clearEffectsByTag(Tag.TERRAIN,true,true); } CombatLog.addLogMessage("Terrain modifier removed!"); param1.showEffects(); return true; } return false; }
So this code, as far as I understand it, is looking at two things to trigger: the place on the combat field (param1) and if that location already has a Terrain (param1.terrainTypeId). So, when we base our new code off it, it will have to be modified to not bother checking if the location already has a Terrain:
private function applyTerrainLooseFooting(param1:BattleGridIndicator) : Boolean { if(param1) { param1.setTerrainModifier(Terrain.LOOSE_FOOTING); CombatLog.addLogMessage("The ground became unstable!"); param1.showEffects(); return true; } return false; }
And finally an analog to the "destroysTerrain" if statement:
if(this.skill.applyLooseFooting && _loc25_) { this.applyTerrainLooseFooting(_loc25_.grid); }
The end result is the skill is functionally sound: it deals damage to each opponent, removes Terrains from each square with those opponents, and then applies the Terrain Loose Footing regardless if it removed a Terrain or not.

However, while the skill does prompt the -[Terrain] floating text, it doesn't show floating text for adding Loose footing. I'm guessing the difference has to do with "param1.charRef.clearEffectsByTag", but we're looking to add effects, not clear them. So I just left it off rather than look up a different function. It's not perfect, but it works.
18 Comments
Rekin 27 Feb @ 1:22pm 
How is the class modes?
1 Adding a different tree to the class
2 Unlocking the class without the necessary reputation of the faction or the completion of the campaign
3 Unlocking or blocking for armor or inventory trees
O-Ha 24 Jun, 2022 @ 12:10pm 
I made a mod!
also, @unsterblichenvogel,
You got what you wished for!

It adds quite alot of cools stuff, will add more content as I go, so far:
1) Grid is now 3x3
2) Battles are much faster
3) You can overide default attack
4) COMPLETE STACKING + DRAG AND DROP SYSTEM
5) respec now return stat points as well
6) New Items, that give you access to a third skill tree and remove subclass restrictions and artifact strain, will be quite hard to get though.

Have FUN! :D

https://drive.google.com/file/d/1bN4ro2bsJhNx5VVkzGi9WGVFv5f1ybjh/view?usp=sharing


Installation Guide:
1) extract the files to your monster den directory
2) run the installer that fit your os
3) done!


If you want to see more stuff and previews of new content go to Monster's Den Discord:
https://discord.gg/gfZPHV5DcE
unsterblichenvogel 3 Apr, 2022 @ 8:27pm 
Is there Any Mod to make the Item Stacked just like book of Dread?
Rebel Uccidere 3 Nov, 2019 @ 3:11pm 
wats dis OwO
Immo 3 Feb, 2019 @ 6:05am 
Hey Parabola, about your point 2) how is your disc space doing XD
Can't you solve it in a super easy way by copying all files to some magnetic disc and doing hundreds of backups and new versions there :O This way you won't ever lose your progress, unless you throw the disc to a Microwave I guess ;p
Immo 3 Feb, 2019 @ 6:02am 
here a forum thread with some questions about modding
https://gtm.steamproxy.vip/app/469720/discussions/0/1778261844037071749/
Parabola01  [author] 15 Jan, 2019 @ 1:55pm 
@GwenBlanketKnight[2.2ModPosted]
I modded in a custom class tree, complete with skill books for the Ascended class. It was called the Expert, iirc, and I put in a bunch of the best skills in the game into one tree. As for unlocking it, I just overrided the the Trickster character with it. Making your own clas to unlock looked to be more complex than overriding.

I'm probably not going to update this guide until 2 things happen:
1.) I'm done with grad school
2.) Garin signals he's done with updates and I don't have to worry about losing mod progress.

Long term, I have plans to make an overhaul mod if I can figure it out. It will likely take way too much time and I'm not going to worry about doing it until I'm out of grad school.
GwenBlanketSpecter 10 Jan, 2019 @ 3:16am 
Is it possible to mod in classes? It would nice if every skill combination existed. i would be willing to go to the effort of doing it myslef and sharing with the community if its possible. Unlock them the way the tracker is probably.
Immo 17 Sep, 2018 @ 9:13am 
I paste here threads with suggestions, because every time I do a new mod, I look for them all over the place...

sum up of old threads: https://gtm.steamproxy.vip/app/469720/discussions/0/1727575977582359287/

DoT, Crossbows: https://gtm.steamproxy.vip/app/469720/discussions/0/1727575977568303011/

Storied set vs Epic set (rebalance) https://gtm.steamproxy.vip/app/469720/discussions/0/1727575977550087373/

Quests, Champion monster stat-bonus:
https://gtm.steamproxy.vip/app/469720/discussions/0/1727575977598313781/