Jump to content

Lindor's Mod for Sacred 2 EE development Thread


Lindor

Beta version yes or no?  

1 member has voted

  1. 1. Should i publish an early test version of my unfinished mod?

    • Yes, I want to participate in playtesting.
      0
    • Generally I'd like a Beta version, but if it's really so unfinished yet, you should work on it a little bit more first.
      1
    • No, don't publish until it's perfect.
      0


Recommended Posts

Actually I thought about this: it might be possible to automatically start s2rw at the launch of each game session and compile the global.res file.

I would create an exe which first generates the blueprint ID file, then generates the hashes and inserts them into a decompiled and cleaned up global.res file, then fires s2rw to compile the global.res and then finally launches the Sacred 2 exe.

 @Flix I think I've read somewhere that your friend Pesmontis won't come back to Sacred 2 modding, can you ask him wether it's okay when I use s2rw in my mod?

Link to comment
On 6/30/2022 at 4:35 AM, Lindor said:

EDIT: okay this is a wierd idea, but I think it may be possible to use ItemnamesMaterial.csv. for each item with a fixed name it would be required to duplicate the material used in material.txt, then name the material by some scheme and then manipulate itemnamesMaterial.csv to assign the name as scripted in the files to the item which uses said material. And that all needs to be automated. But how on earth can be made sure that the name is assigned by the material and not by the boni?

I'm currently not going with this idea, but it would be possible. One can set it so that very rare items only get their name generated through the material in NameGenConfig.txt in each locale folder.

15 hours ago, Lindor said:

at the launch of each game session

I realized that the ID, hash and name generation doesn't need to take place at the launch of each game session, it only needs to take place after a modder added an item or changed an item name. So I will provide an exe for modders which does all of this automatically, but it doesn't need to get uploaded with the mod.

Because the IDs won't change each game session, they will remain static. But not hard-assigned, the order is random and changes each time you launch the ID/hash/global.res generation exe.

Link to comment
On 6/30/2022 at 4:55 PM, Lindor said:

I think I've read somewhere that your friend Pesmontis won't come back to Sacred 2 modding, can you ask him wether it's okay when I use s2rw in my mod?

Just send him a message. He's still active, I just heard from him the other day.  I'm sure it would be fine.

Link to comment
58 minutes ago, Flix said:

Just send him a message. He's still active, I just heard from him the other day.  I'm sure it would be fine.

Alright :)

-------

Some Sacred 2 system's lua specifics:

  • It is possible to load modules from inside the game scripts (aka using the require() function, the function IS supported!). The specifics for loading modules from inside a script are:
    • You have to specify the full file path, otherwise the module won't load
    • You have to use double backslashes and not normal slashes when specifying the file path, otherwise the whole game script will crash
    • You can but don't have to specify the module's ".lua" file extension
  • It is also possible to specify additional scripts to load in autoexec.exe.
  • Librarys which are standardly included in lua like the I/O library and the os library are NOT supported as far as I can tell. io.read(), io.write(), os.execute() etc. all crash the game script, so it won't load.
  • Unless it's autoexec.txt, the game will still launch normally even if a game script crashes during the execution process
  • What I haven't tested yet is launching exe's from autoexec.txt. sys.execScript() might only work for .txt files, and the Sacred 2 lua API is not known and all commands which aren't specified somewhere in a game script need to be found by pure guessing. (Well unles your name is Dmitriy:D)

 

Link to comment

@Flix @dimitrius154

I have a balancing question:

Artifacts can only have defensive boni (at least in my mod).
With that in mind as an example for what I mean, what do you think about separation of boni between armor and weapons? I'm not thinking strict separation, but some boni can only spawn on weapons, some on armor and some on both.

Is this generally a thing which you want to have the option to include in your mods or is it okay if weapons and armor can both have the same boni?

I'm talking only about items without fixed boni so that the boni are generated by the automated bonusgroup generation.

Link to comment

Actually I think I made a decision.

The goal of my efforts is to mostly keep the mod's balance and just transform the syntax into an easier moddable, better correctable and more uniform state. It's supposed to keep the same balance over all items depending on the type of the item. So I'm gonna keep the feature of weapon boni and give the modder the ablilty to quickly change it if he/she wants to.

I think I'm gonna determine what's considered a weapon bonus by wether it's modified by a weapon lore skill/mastery or not.

Oh boy, sooo much work to do:D

Link to comment

Does someone know wether "Chance_to_hit_additional_opponents" works with ranged weapons?

EDIT: and can deep wounds and deadly wounds as an item modifier be triggered by spell damage?

Actually, I need to know this for all four wounds effects. As an item modifier, which of those work with spell damage?

Edited by Lindor
Link to comment

I think I have finished my bonuslist:

Spoiler
--everything which is not defined is set to "false" by default. This makes it easier for me to set up the main logic in blueprint.txt.
--
--The module basedonskill.lua determines wether the modifier can spawn on weapons or on armor or on both (which can be disabled in balance.lua). It is not set here. basedonskill.lua draws its properties directly from the initial blueprint.txt on enabling to preserve balance. Can get modified.
--The module defense.lua determines which modifiers can spawn on artefacts. Again, gets generated from original blueprint.txt upon enabling to preserve balance. Can get modified.
--
--spez: first parameter: setup as in spez_all.lua module. second parameter: 0=optional, 1=required.                       Remember that spez can never equal spez2 unless they're both an empty string. If spez == "", then automatically spez2 is set as "" as well. Both of this is ensuread at the Bonus generation function level.
--tier: tier if requirements are not met, tier if requirements are met, requirements for spez, requirements for spez2     Tiers range from 0-5. You can change that, but then you also need to change the min and max bonus tiers in balance.lua
--possible dmgflag's: "weapon", "melee", "ranged", "spell"                                                                This means "affects or can be triggered by this damage class dealt by the player". It does NOT care about "damage received by the player"! Don't confuse these on things like BONUS_EVADE.
--flags: spell token, item, creature, consumable                                                                          2 means untested, 1 means works, 0 means doesn't work. in the logic, 2 is treated as 0.

local properties = {
    BONUS_ADDCA = {
        spez = {"#ASPECT", 0}, --if spez === "", then all aspects are addressed. Only works if spez2 == "" as well, as stated above.
        spez2 = {"#CA", 1}, --Theoretically not required, but if spez2 == "", then all CA in aspect are addressed. Same as BONUS_ADDCA_ASPECT, therefore unnecessary duplicate.
        tier = {3, false, false, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_ADDCA_ASPECT = {
        spez = {"#ASPECT", 1},
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_ADDCA_HORSE = {
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {0, 0, 1, 0}
    },
    BONUS_AREARADIUS = { --Combat art range. Good with most spells but bad with meteors.
        spez = false,
        spez2 = false,
        tier = {2, false, false, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_AREASPLASH = { --Chance to hit additional opponents.
        spez = false,
        spez2 = false,
        tier = {2, false, false, false},
        dmgflag = "weapon" --not sure wether works with ranged
        flags = {1, 1, 2, 2}
    },
    BONUS_ARMOR = { --actually I'm thinking about increasing it to tier 4
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = false,
        flags = {1, 1, 1, 2}
    },
    BONUS_ARMOR_REL = {
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_BANISH_UNDEAD_POTENTIAL = { --tier doesn't matter, only works on consumables
        spez = {"#POTION", 1},
        spez2 = false,
        tier = {}
        dmgflag = false,
        flags = {2, 2, 2, 1}
    },
    BONUS_BLEEDING = { --Dotdamage is very good on enemies since you live very long and have little possibilities to decrease it, but it's bad on the player since most enemies don't live long enough to take a lot of damage from it. And if they do live long enough, there's something wrong with the character build I'd say.
        spez = false,
        spez2 = false,
        tier = {2, false, false, false},
        dmgflag = false,
        flags = {1, 1, 1, 2}
    },
    BONUS_CAN_HEAL = { --tier doesn't matter, only works on consumables
        spez = false,
        spez2 = false,
        tier = {}
        dmgflag = false,
        flags = {2, 2, 2, 1}
    },
    BONUS_CA_MULTIPLIER = { --god tier damage, originally used only for spell tokens (et_missile_adapt, et_cone_adapt)
        spez = false,
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_CA_WEAPONDMG_MULTIPLIER = { --et_mult_weapondamage
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = "weapon",
        flags = {1, 2, 2, 2}
    },
    BONUS_CHANCE_BANISH_UNDEAD = {
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_CHANCE_BLOCKDAMAGE = { --ALL BLOCK boni, not just damage.
        spez = {"#BLOCK", 1},
        spez2 = false,
        tier = {1, 3, {"BLOCK_CLOSECOMBAT", "BLOCK_MISSILE", "BLOCK_SPELL"}, false},
        dmgflag = false,
        flags = {1, 1, 1, 2}
    },
    BONUS_CHANCE_BLOCK_KNOCKBACK = {
        spez = false,
        spez2 = false,
        tier = {1, 3, false, false},
        dmgflag = false,
        flags = {2, 1, 1, 2}
    },
    BONUS_CHANCE_CALL_TARGET = { --et_call_target, et_minion_blame
        spez = false,
        spez2 = false,
        tier = {},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_CHANCE_DOUBLEHIT = {
        spez = false,
        spez2 = false,
        tier = {4, 3, false, false},
        dmgflag = "melee",
        flags = {1, 1, 2, 2}
    },
    BONUS_CHANCE_FLEE = {
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_CHANCE_KNOCKBACK = {
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_CHANCE_MINION = { --et_minion_raise
        spez = false,
        spez2 = false,
        tier = {}
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_CHANCE_MINION_INFECT = { --et_minion_infect
        spez = false,
        spez2 = false,
        tier = {3, false, false, false}
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_CHANCE_ROOT = {
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_CHANCE_SLOWDOWN = {
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_CHANNELDAMAGE_CONVERSION = {
        spez = {"#DMG", 1},
        spez2 = {"#DMG", 1},
        tier = {3, false, false, false},
        dmgflag = "weapon",
        flags = {1, 1, 1, 2}
    },
    BONUS_CHANNEL_CONV_TO_BEST = {
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = "weapon",
        flags = {1, 2, 2, 2}
    },
    BONUS_CHARGE_ATTR = { --et_charge_AW_rel, et_charge_attackspeed, shadow warrior killing spree
        spez = {"#CHARGE", 1},
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_CHARGE_MORPH = { --bb_charge_morph_duration (hardcoded into it), otherwise unused, tier doesn't matter, ID must be preserved
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_CLOSE_BUFF = { --et_closedown_buff
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_COMBATVALUE = {
        spez = {"#CBTVAL", 1},
        spez2 = false,
        tier = {2, false, false, false},
        dmgflag = "weapon",
        flags = {1, 1, 1, 2}
    },
    BONUS_COMBATVALUE_REL = {
        spez = {"#CBTVAL", 1},
        spez2 = 
        tier = {3, false, false, false},
        dmgflag = "weapon",
        flags = {1, 1, 1, 2}
    },
    BONUS_CRITICALHIT = {
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = "weapon",
        flags = {1, 1, 1, 2}
    },
    BONUS_DAMAGE_ANY_REL = {
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {4, 5, {"DMG_MAX"}, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_DAMPING = {
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = false,
        flags = {1, 1, 1, 2}
    },
    BONUS_DAMPING_TEAMSHARE = { --et_damping_teamshare, inquisitor reverse polarity
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_DEATHBLOW = {
        spez = false,
        spez2 = false,
        tier = {2, false, false, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_DEBUFF = {
        spez = {"#DEBUFF", 1},
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_DEBUFF_ARMOR_POTENTIAL = {
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {3, 5, {"DEBUFF_STATS"}, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_DEBUFF_POTENTIAL = {
        spez = {"#DEBUFF", 1},
        spez2 = false,
        tier = {3, 5, {"DEBUFF_STATS"}, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_DEBUFF_WITH_ESSENCE = {
        spez = {"#DEBUFF", 1},
        spez2 = false,
        tier = {3, 5, {"DEBUFF_STATS"}, false},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_DEEPWOUND = { --deep wounds
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = "weapon", --guess. keep in mind that dmgflag is only applied to the bonus as an item modifier.
        flags = {1, 1, 2, 2}
    },
    BONUS_DIRECTDAMAGE = {
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = "weapon",
        flags = {2, 1, 1, 2}
    },
    BONUS_DISARM = { --et_chance_disarm
        spez = false,
        spez2 = false,
        tier = {1, false, false, false},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
--    BONUS_DISMOUNT = { --broken
--        spez = false,
--        spez2 = false,
--        dmgflag = false,
--        flags = {1, 1, 2, 2}
--    },
    BONUS_DOTDAMAGE = {
        spez = {"#DMG", 1}, --I actually don't know wether DMG_MAX is a possibility
        spez2 = {"#SUBFAM", 0},
        tier = {2, false, false, false}, --same explanation as for bleeding
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_DOTDAMPING = {
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
--    BONUS_DROPCHANCE = { --broken, maybe item dropchance works because it has tooltip but not sure
--        spez = {"#DRPC", 1},
--        spez2 = false,
--        tier = {0, false, false, false},
--        dmgflag = false
--        flags = {2, 2, 2, 2}
--    },
    BONUS_ENERGYLEECH_ONCE = { --et_energy_leech_once, e.g. in_uw_seelenraub
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false, --guess
        flags = {1, 2, 2, 2}
    },
    BONUS_ENERGYLEECH_WHIT = { --WHIT == weapon hit. Super OP.
        spez = false,
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = "weapon",
        flags = {1, 1, 2, 2}
    },
    BONUS_ENERGY_ANIHILATION = { --et_energy_anihilation, enemy spells only, e.g. boss_auge_traps_kk
        spez = false,
        spez2 = false,
        tier = {0, false, false, false}, --SUUUPER OP and annoying for enemies, extremely bad for player characters and that's what matters
        dmgflag = "weapon", --guess, may very well work with spell dmg. doesn't matter until it's confirmed that it works as item modifier.
        flags = {1, 2, 2, 2}
    },
    BONUS_ENHANCEPOTION = {
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_EVADE = {
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = false,
        flags = {1, 1, 1, 2}
    },
    BONUS_EVADE_DETECTION = {
        spez = false,
        spez2 = false,
        tier = {0, false, false, false}, --really depends on your playstyle though. ranges from garbage to absolutely necessary.
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_EXPERIENCE = {
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {2, 2, 1, 2}
    },
    BONUS_EXPERIENCE_REL = {
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_EXTRAEFFECTCHANCE = {
        spez = {"#DMG", 1}, --don't know wether DMG_MAX works
        spez2 = false,
        tier = {2, 4, {"DMG_MAGIC"}, false}, --DoT is bad, but freeze is good and weaken is tier 4, maybe even tier5.
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_FACTION_MODIFIER = { --turns enemies into 1-XP-chickens/rabbits. More a malus than a bonus
        spez = {"#FACTION", 1},
        spez2 = {"#FACTION", 1},
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {2, 2, 1, 2}
    },
    BONUS_GOLD_REL = {
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_HURL_ENEMY = {
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = false, --guess, don't know for sure, but doesn't matter until it's proven that it works with items
        flags = {1, 2, 2, 2}
    },
    BONUS_IGNORE_ARMOR = {
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = "weapon"
        flags = {2, 1, 2, 2}
    },
    BONUS_INVALID = {
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {2, 2, 2, 2}
    },
    BONUS_INVERT_ARMOR = {
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false, --guess, don't know for sure, but doesn't matter until it's proven that it works with items
        flags = {1, 2, 2, 2}
    },
    BONUS_INVISIBLE = {
        spez = {"#BINARY", 0}, --if spez == "", then it will activate if creature visible and deactivate if creature invisible. if spez == 1, it will only activate. if spez == 0, it will only deactivate.
        spez2 = false,
        tier = {2, false, false, false}, --really depends on your playstyle
        dmgflag = false,
        flags = {1, 2, 1, 2}
    },
    BONUS_LEVEL_ALL_CA = {
        spez = false,
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = false,
        flags = {2, 2, 1, 2}
    },
    BONUS_LIFELEECH = {
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = "weapon",
        flags = {1, 1, 1, 2}
    },
    BONUS_LIFELEECH_REL = {
        spez = false,
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = "weapon",
        flags = {1, 1, 2, 2}
    },
    BONUS_LIFEPOINTS = {
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_LIFE_REGENERATION = {
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_LIFE_REGENERATION_REL = { --originally used as creaturebonus, also works on spells and items
        spez = false,
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = false,
        flags = {1, 1, 1, 2}
    },
    BONUS_LIFE_REL_MOUNTED = {
        spez = false,
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = false,
        flags = {2, 2, 1, 2}
    },
    BONUS_LIGHTRANGE = {
        spez = false,
        spez2 = false,
        tier = {0, false, false, false}, --only considering combat value. It's actually a nice bonus.
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_LOADSINGLECHARGE = { --bb_load_singlecharge, rage mod from shadow warrior scything sweep
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false, --guess, doesn't matter until proven that it works with items
        flags = {1, 2, 2, 2}
    },
    BONUS_LOWCOST = { --chance to halve regeneration time
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
--    BONUS_LOWERARMOR = { --broken
--        spez = false,
--        spez2 = false,
--        tier = {4, false, false, false},
--        dmgflag = false,
--        flags = {1, 2, 2, 2}
--    },
    BONUS_MAGICFIND = {
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_MENTOR = {
        spez = {"#POTION", 1},
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {2, 2, 2, 1}
    },
    BONUS_MISSILE_SLOWDOWN = { --et_missile_slowdown, dm_me_mahlstrom
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_MORTALSTRIKE = { --deadly wounds
        spez = false,
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = "weapon", --guess, not sure
        flags = {2, 1, 1, 2}
    },
    BONUS_NEUTRALIZE_DOT = {
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_NOEVADE = {
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = "weapon", --can't evade spell damage anyway
        flags = {2, 1, 2, 2}
    },
    BONUS_NOFLEE = { --doesn't make sense to give the player fear resistance, already can't be feared. But might make sense to give the target of spells fear resistance.
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {0, 0, 1, 0}
    },
    BONUS_PAINLIMIT = {
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_PIERCING = {
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = "ranged",
        flags = {1, 1, 2, 2}
    },
    BONUS_PLAGUE = {
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {2, false, false, false},
        dmgflag = "spell", --guess
        flags = {1, 2, 2, 2}
    },
    BONUS_PLAGUE_DOT = {
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {2, false, false, false},
        dmgflag = "spell", --guess
        flags = {1, 2, 2, 2}
    },
    BONUS_PLAGUE_INFECTION = {
        spez = false,
        spez2 = false,
        tier = {2, false, false, false},
        dmgflag = "spell", --guess
        flags = {1, 2, 2, 2}
    },
    BONUS_PRONETOCHANNEL = { --originally used as creaturebonus only
        spez = {"#DMG", 1},_FIRE
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {1, 2, 1, 2}
    },
    BONUS_RANGEOFSIGHT = {
        spez = false,
        spez2 = false,
        tier = {0, false, false, false}, --only considering combat value, it's actually a nice bonus to have
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_REDUCE_BUFFUPKEEPCOST = {
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_REDUCE_DEBUFFS = {
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_REDUCE_ENEMYS_CC_REFLECTION = {
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = "melee",
        flags = {2, 1, 1, 2}
    },
    BONUS_REDUCE_ENEMYS_MISSILEREFLECTION = {
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = "ranged",
        flags = {2, 1, 2, 2}
    },
    BONUS_REDUCE_ENEMYS_SPELL_REFLECTION = { --originally used as creaturebonus only
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = "spell",
        flags = {1, 1, 1, 2}
    },
    BONUS_REDUCE_EXTRAEFFECTCHANCE = {
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_REFLECTION = {
        spez = {"#REFL", 1},
        spez2 = false,
        tier = {4, false, false, false}, --from my feeling between 3 and 4, went for 4
        dmgflag = false,
        flags = {1, 1, 1, 2}
    },
    BONUS_REGEN_ASPECT = {
        spez = {"#ASPECT", 1},
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = false,
        flags = {1, 1, 1, 2}
    },
    BONUS_RIPPER = { --serious open wounds
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = "weapon" --guess
        flags = {2, 1, 2, 2}
    },
    BONUS_SELFDESTRUCT = { --et_minion_lifetime, et_minion_fighttime
        spez = false,
        spez2 = false,
        tier = {0, false, false, false},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_SHIELD = { --Flix means it doesn't do anything. Used for shield strength token of seraphim (et_shieldstrength, et_shieldstrength_timed). This token works, but the bonus might be hardcoded and not drawn from the bonus.
        spez = false,
        spez2 = false,
        tier = {3, false, false, false}, --atually might be extremely OP since it doesn't just add flat shield points, it adds base shield points! Multiplicative with BONUS_SHIELD_REL! If proven that works on items, tier needs to be increased to 5.
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_SHIELDBLOCK = { --et_shieldblock, blocks fixed amount of damage from every hit
        spez = false,
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_SHIELDFACTOR = { --%amount of damage which gets applied to shield instead of health, standard 50% for buff, 100% for temporary buff
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_SHIELDFACTOR_IGNORE = { --penetrate shields, dmg gets applied at health instead of shield
        spez = false,
        spez2 = false,
        tier = {1, false, false, false}, --very few enemies have shields
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_SHIELDFACTOR_IGNORE_POTENTIAL = { --originally used as creaturebonus, should work on items. On spells it might grant the enemies the ability to penetrate player shields.
        spez = false,
        spez2 = false,
        tier = {1, false, false, false}, --very few enemies have shields
        dmgflag = false,
        flags = {2, 1, 1, 2}
    },
    BONUS_SHIELD_REGENERATION = { --Temple Guardian regeneration during combat
        spez = false,
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = false,
        flags = {1, 2, 1, 2}
    },
    BONUS_SHIELD_REL = {
        spez = false,
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = false,
        flags = {2, 1, 1, 2}
    },
    BONUS_SHIELD_RELOAD_REL = { --et_shield_reload_rel, boss_golem_erdbeben only spell which uses that. Quite common as item modifier, %shield regen. Only out-of-combat.
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = false,
        flags = {1, 1, 2, 2}
    },
    BONUS_SHRINKHEAD_DROPCHANCE = {
        spez = false,
        spez2 = false,
        tier = {3, false, false, false}, --only drop chance bonus which has in-combat relevance to me since yellow/green shrinkheads are so rare.
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
--    BONUS_SHRINKHEAD_ESSENCE = { --does not have in-game tooltip. Would not be good to spawn randomly on items. Use as static hard-assigned bonus only.
--        spez = {"#SUBFAM", 1},
--        spez2 = false,
--        tier = {4, false, false, false},
--        dmgflag = false,
--        flags = {2, 1, 2, 2}
--    },
    BONUS_SKILL = {
        spez = {"#SKILL", 1},
        spez2 = false,
        tier = {3, 5, {"SKILL_ANY", "SKILL_DEF", "SKILL_ATT", "SKILL_CA"}, false},
        dmgflag = false, --actually depends on skill. that's what dmgflag_#SKILL.lua is for.
        flags = {1, 1, 2, 2}
    },
--    BONUS_SLOT = { --slots are different, not applied via standard bonusgroup generation
--        spez = {"#SLCAT", 1},
--        spez2 = false,
--        tier = {3, false, false, false},
--        dmgflag = false,
--        flags = {2, 1, 2, 2}
--    },
    BONUS_SPEED = {
        spez = {"#SPEED", 1},
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = false, --actually depends on speed. that's what dmgflag_#SPEED.lua is for.
        flags = {1, 1, 1, 2}
    },
    BONUS_SPEED_LIMIT = { --et_attackspeed_limit, in_in_eifer. Prob doesn't work with casting speed since there is no limit
        spez = {"#SPEED", 1},
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false, --actually depends on speed. that's what dmgflag_#SPEED.lua is for.
        flags = {1, 2, 2, 2}
    },
    BONUS_SPELLDAMAGERANGE = {
        spez = {"#DMG", 1},
        spez2 = {"#SUBFAM", 1},
        tier = {5, false, false, false},
        dmgflag = "spell",
        flags = {1, 2, 2, 2}
    },
    BONUS_SPELLDAMAGERANGE_WITH_ESSENCE = {
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = "spell",
        flags = {1, 2, 2, 2}
    },
    BONUS_SPELL_INTENSITY = {
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = "spell",
        flags = {1, 1, 2, 2}
    },
    BONUS_SPELL_RESISTANCE = {
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = "spell",
        flags = {2, 1, 2, 2}
    },
    BONUS_STATS = {
        spez = {"#STAT", 1},
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {2, 1, 1, 2}
    },
    BONUS_STATS_REL = {
        spez = {"#STAT", 1},
        spez2 = false,
        tier = {5, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_STUN = {
        spez = false,
        spez2 = false,
        tier = {3, false, false, false}, --depends. good vs boss, bad vs everything else
        dmgflag = "weapon", --guess
        flags = {1, 1, 1, 2}
    },
    BONUS_SUPERCHARGE = { --et_supercharge, sk_tc_kampfrausch
        spez = false,
        spez2 = false,
        tier = {3, false, false, false},
        dmgflag = false,
        flags = {1, 2, 2, 2}
    },
    BONUS_SUREHIT = {
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = "weapon",
        flags = {2, 1, 2, 2}
    },
    BONUS_SURVIVAL_REL = {
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = false,
        flags = {2, 1, 2, 2}
    },
    BONUS_TARGET_SEEKER = { --et_target_seeker
        spez = false,
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = "spell", --guess, might also be "ranged". doesn't matter until proven that it works as item modifier
        flags = {1, 2, 2, 2}
    },
    BONUS_WEAPONDAMAGERANGE = { --et_weapondamage_phy/mag/fir/poi/ice
        spez = {"#DMG", 1},
        spez2 = false,
        tier = {4, false, false, false},
        dmgflag = "weapon",
        flags = {1, 1, 1, 2}
    },
    BONUS_WEAPONDAMAGE_REL = { --e.g. et_damage_weapon_rel, but also some sb_/cr..._
        spez = {"#DMG", 1},
        spez2 = {"#SUBFAM", 1},
        tier = {5, false, false, false},
        dmgflag = "weapon",
        flags = {1, 1, 1, 2}
    },
    BONUS_WOUNDEDRAGE = {
        spez = false,
        spez2 = false,
        tier = {3, false, false, false}, --depends on your playstyle, e.g. super bad on energy shield characters.
        dmgflag = false,
        flags = {1, 1, 2, 2}
    }
}

 

@Flix @dimitrius154 Any input/critique/commentary? (and, in case you didn't do already, can you read previous post's questions? I have edited some in, may've gotten overlooked.)

 

Update: With the completion of this file I'm approximately 2/3 of the way to a release of the blueprint.txt mechanics overhaul. Which will be part of my mod if I ever get it to release state.:lol:

Link to comment
  • The title was changed to Lindor's Mod for Sacred 2 EE development Thread
On 7/3/2022 at 1:50 PM, Lindor said:

With that in mind as an example for what I mean, what do you think about separation of boni between armor and weapons? I'm not thinking strict separation, but some boni can only spawn on weapons, some on armor and some on both.

That's already in place, generally, in vanilla.  Uniques in CM Patch and beyond flout those distinctions from time to time.

23 hours ago, Lindor said:

Does someone know wether "Chance_to_hit_additional_opponents" works with ranged weapons?

Seems to work just fine.

23 hours ago, Lindor said:

Actually, I need to know this for all four wounds effects. As an item modifier, which of those work with spell damage?

I think it's just open wounds. The others would need to be added as spell tokens to trigger.

  • Thanks! 1
Link to comment
4 minutes ago, dimitrius154 said:

Most item modifiers have no effect in non-Addendum versions. This one as well.

Wait - what? The whole time I have been stacking deep and deadly wounds on my inquisitor for nothing?:twitch:

I'll disable the four wounds effect as item modifier then.

Link to comment

Wait a minute, serious open wounds exists only as an item modifier. If it doesn't work, then how has been found out what it does?

Also deadly wounds only exists as item modifier or creature bonus.

Deep wounds and bleeding are the only two which exist as spell token.

Link to comment
25 minutes ago, Lindor said:

Wait a minute, serious open wounds exists only as an item modifier. If it doesn't work, then how has been found out what it does?

Also deadly wounds only exists as item modifier or creature bonus.

Deep wounds and bleeding are the only two which exist as spell token.

Because I use them on spells, of course.  :D  Would you like me to upload the D2F scripts so you can look at how far I've pushed things with spells?  I mean, it's not THAT radical, but if you're only looking at EE or Addendum you're only seeing some of the potential.

BTW I thought you avoided D2F because of download size but Addendum is even bigger. 

EDIT: Here are the scripts.  If nothing else it may give some ideas on using spell fx and spell tokens.  Spells, creatures, and blueprint are hand-sorted.

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

  • Thanks! 1
Link to comment
33 minutes ago, Lindor said:

Wait a minute, serious open wounds exists only as an item modifier. If it doesn't work, then how has been found out what it does?

Well, if you hit something with a sword, or an axe, or shoot(and don't miss the mark) it works)

Link to comment
50 minutes ago, Flix said:

I thought you avoided D2F because of download size but Addendum is even bigger. 

True. It took me whole day to download Addendum. Well, Germany and internet... They're no friends.

Link to comment

Is damage from magic staves treated as spell damage, melee damage or ranged damage? Or is it something completely separate?
(In terms of being able to trigger/be affected by item modifier effects)

Oh and BTW:

14 hours ago, Flix said:

but if you're only looking at EE or Addendum you're only seeing some of the potential.

I'm actively avoiding looking at addendum because a lot of stuff works there what normally doesn't work. For D2F it's the same I think? It's just when I'm noticing a potential bug in CM/EE, I'm looking wether addendum has it as well.

The transformation is supposed to be a basis for an easier modding environment for everyone. If the modder changes some hardcoded behaviour, it's intended that he/she also manually changes that in the scripts. E.g. if he/she enables BONUS_ADDCA_HORSE for spells, he/she'd also have to set the spell flag to one in the bonus classification.

Edited by Lindor
Link to comment

Update: I have just finished scripting the bonus name&ID generation module. It dynamically transforms above bonus classification and the list into smth which looks like this (snippet):

(......)  
    bb$BONUS_DISARM$$ = 55,
    bb$BONUS_PIERCING$$ = 56,
    sb$BONUS_PIERCING$$ = 57,
    bb$BONUS_SHRINKHEAD_DROPCHANCE$$ = 58,
    bb$BONUS_WOUNDEDRAGE$$ = 59,
    sb$BONUS_WOUNDEDRAGE$$ = 60,
    bb$BONUS_WEAPONDAMAGE_REL$DMG_FIRE$ = 61,
    bb$BONUS_WEAPONDAMAGE_REL$DMG_FIRE$SUBFAM_LIFE_ANIMAL = 62,
    bb$BONUS_WEAPONDAMAGE_REL$DMG_FIRE$SUBFAM_LIFE_ANIMAL_ATMO = 63,
(.....)

it loads all possible boni in a random order and assigns it IDs, skipping all hardcoded bonus IDs.

As currently, there are 1576 possible different boni and 2 hardcoded boni (bb_charge_morph_duration, crbonus_faction_modifier_enemy_hero).

 

Not sure wther I wanna keep dollar signs as separator or use something which "sticks out more" to the eye, but that's just an aesthetic question and the bonis ID/name correlation list won't be something where modders will look into as it's generated automatically every time you run Update.exe.

 

------

 

On 7/9/2022 at 12:34 PM, Lindor said:

Is damage from magic staves treated as spell damage, melee damage or ranged damage? Or is it something completely separate?
(In terms of being able to trigger/be affected by item modifier effects)

I'm repeating myself because that's kinda a core question, and I'm not sure how to test it ingame. I'd need a bonus where it's absolutely sure that it only works for spell damage and nothing else, and I'd need the same for ranged and melee, and something like this doesn't exist yet. And even if it existed, it would still not satisfy the question because it could still be handled as something completely separate, like hybrid dmg based combat arts.

Edited by Lindor
Link to comment

Oh boy the Sacred 2 code is just pure spaghetti. The devs invented so many different functions which practically do the same thing, just look at weargroups or bonusstrength.

The thing I'm worried about in particular atm is difficultyvluerange.

 

I already have the bonus classification and basedonskill.lua, I don't want to create yet another module for modifying boni. Generally sorting is there to increase the overview, like the sorting of the different itemclasses where e.g. each jewelry item is listed in the same file and there's a file for each itemclass, but here having three or more modules for each bonus is overkill and ripping it apart, not sorting.

 

  1. I'm thinking about normalizing difficultyvaluerange for each bonus. Something like:
      difficultyvaluerange0 = {0,10,20},
      difficultyvaluerange1 = {1,20,40},
      difficultyvaluerange2 = {2,30,60},
      difficultyvaluerange3 = {3,40,80},
      difficultyvaluerange4 = {4,50,100},
    or so. The exact values can be modified in balance.lua then. The downside is that the modders would need to revisit the bonusstrength pretty much everywhere.
     
  2. The other extreme would be extracing and saving each value for each bonus, the values get averaged if there are multiple instances of the same bonus.
     
  3. A middle way would be interpolating the values into a linear function with constant spread per difficulty, then for each bonus only three values, namely f(0), slope and spread, would need to be saved. While it would save memory space and loadtime, at the same time it would probably be a little confusing for modders.
     
  4. Last but not least, I could also go with option 1 but automatically adjust the bonusstrength everywhere upon running Enable.exe. It would be lots of work though and I can't guarantee that the balance is completely unaffected, but imho it's the best option so far. Also it would need to be necessary to implement the bonusstrength correction into the Update.exe, so that everytime you change the normalized difficultyvaluerange in balance.lua, it doesn't affect total strength and just affects scaling.

 

@Flix @dimitrius154 What do you think? I'd be interested to hear your opinions about this.

Edited by Lindor
Link to comment

Actually, there's another step to take beforehand. You'd need to somehow determine the "usage value" of each unique bonus type, so as to apply a correct normalization base. You could, technically, bypass the step by taking a sum of each bonus-of-the-same-type occurence and using a median.

Link to comment
22 minutes ago, dimitrius154 said:

Actually, there's another step to take beforehand. You'd need to somehow determine the "usage value" of each unique bonus type, so as to apply a correct normalization base. You could, technically, bypass the step by taking a sum of each bonus-of-the-same-type occurence and using a median.

Hmmm my idea would be:

for each instance of a bonus used, e.g. for each token of each spell in spells.txt, I'm gonna backtrace to the bonus in blueprint.txt, then multiply the bonus strength of the spell token with the highest difficultyvaluerange value of the bonus, divide it by the new highest difficultyvaluerange value, e.g. 100 if I use above normalization, round it to the next integer and then overwrite the old value with the new one.

So instead of saving the usage value for each bonus, I apply it directly at the bonus usage in the game's txt scripts. You think this can work?

 

EDIT: Oh there's a problem. Some difficultyvalueranges equal 0. I'm guessing it works as Bonus * (1 + difficultyvaluerange) then? And the numbers, are they percentage or per mille?

Edited by Lindor
Link to comment
6 hours ago, Lindor said:

Some difficultyvalueranges equal 0. I'm guessing it works as Bonus * (1 + difficultyvaluerange) then? And the numbers, are they percentage or per mille?

My theory is, those entries are "placeholders", made to conform with the way the spell boni in spells.txt are defined. The value type can be determined via spellst.txt, all I've checked were percentages.

Link to comment
6 hours ago, dimitrius154 said:

My theory is, those entries are "placeholders", made to conform with the way the spell boni in spells.txt are defined. The value type can be determined via spellst.txt, all I've checked were percentages.

So (pseudocode) it's like:

funtion apply(difficultyvaluerange, bonusstrength)
	if difficultyvaluerange == 0 then
		do return bonusstrength end
	else
		local newbonusstrength = (difficultyvaluerange / 100) * bonusstrength
		do return newbonusstrength end
	end
end

?

Link to comment
5 hours ago, Lindor said:

So (pseudocode) it's like

Nope, they've never made it the proper way. There's a major bonus definition function, which does address the "difficultyvaluerange", and there're specific CA function which address current bonus values from CA subentries in spells.txt.

Link to comment
11 minutes ago, dimitrius154 said:

Nope, they've never made it the proper way. There's a major bonus definition function, which does address the "difficultyvaluerange", and there're specific CA function which address current bonus values from CA subentries in spells.txt.

Oh this is so bad. Then it's not even defined for the bonus, but for the CA (and I'm guessing each individual item?). How can anyone ever come up with such a spaghetti idea?

 

Anyway, there's no way anymore to keep the balance for me then. I'm just gonna go with the closest I can do which is to pretend it'd work like the pseudocode above, and accept that it'll change balance. @Flix and @all other interested modders, hope you can live with that.

Link to comment
18 minutes ago, Lindor said:

(and I'm guessing each individual item?)

Fortunately not. Items use the general-issue function.

19 minutes ago, Lindor said:

How can anyone ever come up with such a spaghetti idea?

I think, several people have worked with the same code without coordination, perhaps not while being sober. I certainly wasn't, when I managed to deduce their code.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...
Please Sign In or Sign Up