-
Posts
199 -
Joined
Content Type
Forums
Events
Downloads
Gallery
Mods
News
Store
Posts posted by Bubb
-
-
8 hours ago, Luke said:
Maybe @Bubb could provide us with more info about how it's supposed to work...?
There's barely any code behind it. It updates the creature's target with the supplied object, (for the purposes of rendering the reticle), but does nothing else and never self-terminates.
-
9 hours ago, Luke said:
For @Bubb: apparently, EFF files applied by op283 can bypass / ignore op101. Bug or Feature...? Something else to know about it...?
I can't tell you if it's intended, but of all the opcodes that use EFF files:
op177 - CGameEffectApplyEffect - Checks for immunities to EFF op182 - CGameEffectApplyEffectEquipItem - Does not check for immunities to EFF op183 - CGameEffectApplyEffectEquipItemType - Does not check for immunities to EFF op248 - CGameEffectMeleeEffect - Checks for immunities to EFF op249 - CGameEffectRangeEffect - Checks for immunities to EFF op272 - CGameEffectRepeatingApplyEffect - Checks for immunities to EFF op283 - CGameEffectCurseApplyEffect - Does not check for immunities to EFF
You might be able to abuse the bugged op182; if you supply an empty ITM resref it should apply 100% of the time.
-
-
11 hours ago, polytope said:
Are you sure any degree of MR grants immunity to repulsion (opcode 235) on your game?
Yes:
SpoilerAnd I can confirm it's an EE bug dating back to at least v1.3 — the buggy block doesn't exist in oBG2:ToB's op235.
-
1 hour ago, jmerry said:
On targeting by circle size ... OK, that's an option for a 324 effect. There are presets for "greater than 3" or "less than 4". Though I don't actually know enough about how the game works here.
SPLPROT.2DA => STAT == 0x102 checks against the animation INI field "personal_space", or whatever value the creature currently has it set to.
1 hour ago, jmerry said:And as for what it takes to block a wing buffet, the IESDP is even less helpful. "Note: Some animations are immune to this effect".
The following animations are hardcoded to be immune to op235, (given that the target isn't a party member, I.E has a portrait slot):
Spoiler0x1100 TANARRI 0x1200 DRAGON_RED 0x1201 DRAGON_BLACK 0x1202 DRAGON_SILVER 0x1203 DRAGON_GREEN 0x1204 DRAGON_AQUA 0x1205 DRAGON_BLUE 0x1206 DRAGON_BROWN 0x1207 DRAGON_MULTICOLOR 0x1208 DRAGON_PURPLE 0x1300 DEMOGORGON 0x7300 ELEMENTAL_EARTH 0x7302 SHAMBLING_MOUND 0x7310 ELEMENTAL_FIRE 0x7312 ELEMENTAL_FIRE_PURPLE 0x7314 BURNING_MAN 0x7320 ELEMENTAL_AIR 0x7F2E RAVER 0x7F32 SLAYER 0x7F3B SOLAR 0x7F3C DEVA_MONADIC 0x7F3D MELISSAN 0x7F3E GIANT_FIRE 0x7F3F GIANT_YAGA-SHURA 0xE0F0 GOLEM_ICE
The opcode also has this weird block:
if (this->m_sourceRes.startsWith("SP")) { this->m_effectAmount = (100 - pSprite->m_derivedStats.m_nResistMagic) / 100 * (float)this->m_effectAmount; if (this->m_effectAmount == 0) { return 0; // Terminate } }
It's attempting to dampen the knockback speed with the target's magic resistance, but it fails at casting the first division to a float. If the spell resref starts with "SP" any positive magic resistance will make the speed parameter 0, causing the opcode to immediately terminate.
-
Not much I can do except refixing the quickspell slots not reacting to CGameSprite::AddSpecialAbility().
Edit: This is now fixed in the master version of EEex.
-
The mod uses EEex to pull data directly from the actionbar, so yes, anything that displays via the actionbar's "cast spell" menu will be handled. All spells are displayed unless one of the filters is used, which can limit the view to either Cleric or Mage spells, or by matching a search string.
-
Please Note: EEex is required to use this mod — EEex is (at the time of writing) only available on Windows platforms.
Overview:
This mod seeks to replace the standard actionbar spell selection with an alternative that is more convenient for the player. The primary enhancements over the default spell selection include:
- Displaying all available spells at once, (categorized by level). No more endlessly clicking the right-arrow to get to your 9th level spells!
- A searchable spell list. Know which spell you want to cast? Just type the first couple of characters and press enter.
- The ability to narrow view to only Mage or Cleric spells; useful for Mage/Clerics.
Screenshots:
Installation:
Download: Here
- Install EEex (forum).
- Download the zip file above and copy the contents into your game's base folder.
- Run setup-bubb_spell_menu.exe and follow the prompts to install.
- Make sure to run the game with InfinityLoader.exe after installing EEex.
Mod Compatibility:
Compatible with the following UI overhauls, (when installed after):
- Dragonspear UI++, (at the time of writing, the latest version can be found in this comment by artyfox; this version is required for compatibility)
- EET, EET_GUI
- Infinity UI++
- LeUI, LeUI-BG1EE, LeUI-IWDEE, LeUI-SoD
UI tweaks can go anywhere in the installation order relative to this mod.
-
That error usually happens if you've manually gone and downloaded the outdated InfinityLoader release from GitHub. As EEex's readme says:
QuotePlease note: The following links are NOT intended to be used for installing EEex; the loaders are bundled in their respective EEex versions and will be automatically installed alongside EEex.
Just install EEex — don't worry about the loader, it'll install as a part of setup-EEex.exe.
-
That block works fine on my end. Maybe another mod is messing with the stat?
-
197 is a hardcoded projectile that plays SHAREA.BAM.
-
1 hour ago, argent77 said:
However, I'm not sure if this string is actually shown in BG:EE when you talk to a character without valid dialog.
The engine displays it when:
Action #139 PlayerDialog(): [ Dialog forced because MoveToObject() failed, (I haven't observed this ever happening) AND Fails to enter dialog window ] OR [ Fails to enter dialog window AND SPEECH.2DA => EXISTANCE has no valid entries on target cre AND SPEECH.2DA => SELECT_COMMON has no valid entries on target cre AND [ target EA != ENEMY || SPEECH.2DA => HOSTILE_DIALOG has no valid entries on target cre ] ]
The string gets trimmed when being displayed so it doesn't really matter if that leading space is there or not.
-
0xF00041 doesn't have a leading space in my BG2:EE installs: "has nothing to say to you."
0xF00070 and 0xF000C5, ("Find Trap Mode " and "Turn Undead Mode "), appear unused — the engine doesn't reference them.
0xF0010F and 0xF00110, ("Party AI Off " and "Party AI On"), as lefreut says, are only referenced in UI.MENU by their real strref:
function getPartyAITooltip() if aiButtonToggle == 1 then return Infinity_FetchString(15918) else return Infinity_FetchString(15917) end end
Kinda defeats the point of the enginest entry.
-
Ok, I'll attempt to explain how op272's Type=3 works and why it's buggy. First, some things you need to know before I get to the opcode:
- The main engine loop ticks along at the set FPS value, normally 30tps. I will call this an "engine tick".
- Creature AI ticks at random mutiples of the engine ticks based on the object's internal ID. Normal creatures tick every other engine tick, Hastened creatures tick every engine tick, Slowed creatures tick every 4 engine ticks.
- The persistent effect list is updated every AI tick as long as the game is unpaused. 15 of these updates constitute a period. Note how AI ticks can occur at 15tps, 30tps, or 7.5tps given the state of the creature.
- "world time" ticks every other engine tick while the game is unpaused; spells use world time for duration.
Now, how op272 Type=3 works:
1) The world time the effect is decoded at is stored at .EFF +0x6C. This decode happens when the effect is added to the projectile, (I.E. at the end of casting), NOT when the effect is applied to the target.
2) When the effect is applied to the target the engine decides how long it will wait until applying op272's resref field. It does this via:
m_periodCounter = (<current world time> - <decode time>) / 15 % m_period // where m_period is Param1 when using type Param2=3
3) Remember how a period is 15 AI ticks? The persisent effect list keeps track of a creature-wide count of how many times it has been ticked. Every 15 AI ticks of this creature-wide counter => m_periodCounter increments and op272 checks if it should apply its resref. For type Param2=3, the resref is applied once the following is satisfied:
++m_periodCounter >= m_period
Once op272's resref is applied the process starts over from step 2.
Let's step through a real example to see how the above works, Param2=3, Param1=2:
Spoilerop272 decoded on worldTime: 5453054 op272 applying on worldTime: 5453062, m_periodCounter: 0 op272 applying on worldTime: 5453063, m_periodCounter: 0 15th AI Update on worldTime 5453065, m_periodCounter: 1 15th AI Update on worldTime 5453080, m_periodCounter: 2 Repeating effect applied [+26 from decode] op272 applying on worldTime: 5453081, m_periodCounter: 1 15th AI Update on worldTime 5453095, m_periodCounter: 2 Repeating effect applied [+15 from last apply] op272 applying on worldTime: 5453096, m_periodCounter: 0 15th AI Update on worldTime 5453110, m_periodCounter: 1 15th AI Update on worldTime 5453125, m_periodCounter: 2 Repeating effect applied [+30 from last apply] op272 applying on worldTime: 5453126, m_periodCounter: 0 15th AI Update on worldTime 5453140, m_periodCounter: 1 15th AI Update on worldTime 5453155, m_periodCounter: 2 Repeating effect applied [+30 from last apply] op272 applying on worldTime: 5453156, m_periodCounter: 0 15th AI Update on worldTime 5453170, m_periodCounter: 1 15th AI Update on worldTime 5453185, m_periodCounter: 2 Repeating effect applied [+30 from last apply] ...
The system works OK at normal AI speed. However, if a creature is hastened it sneaks in extra applications. Consider:
Spoilerop272 decoded on worldTime: 5453044 op272 applying on worldTime: 5453054, m_periodCounter: 0 op272 applying on worldTime: 5453054, m_periodCounter: 0 15th AI Update on worldTime 5453054, m_periodCounter: 1 15th AI Update on worldTime 5453062, m_periodCounter: 2 Repeating effect applied [+18 from decode] op272 applying on worldTime: 5453062, m_periodCounter: 1 15th AI Update on worldTime 5453069, m_periodCounter: 2 Repeating effect applied [+7 from last apply] op272 applying on worldTime: 5453070, m_periodCounter: 1 15th AI Update on worldTime 5453077, m_periodCounter: 2 Repeating effect applied [+8 from last apply] op272 applying on worldTime: 5453077, m_periodCounter: 0 15th AI Update on worldTime 5453084, m_periodCounter: 1 15th AI Update on worldTime 5453092, m_periodCounter: 2 Repeating effect applied [+15 from last apply] op272 applying on worldTime: 5453092, m_periodCounter: 1 15th AI Update on worldTime 5453099, m_periodCounter: 2 Repeating effect applied [+7 from last apply] op272 applying on worldTime: 5453100, m_periodCounter: 1 15th AI Update on worldTime 5453107, m_periodCounter: 2 Repeating effect applied [+8 from last apply] op272 applying on worldTime: 5453107, m_periodCounter: 0 15th AI Update on worldTime 5453114, m_periodCounter: 1 ...
Slow appears to work OK most of the time, though maybe I've missed something:
Spoilerop272 applying on worldTime: 5453113, m_periodCounter: 0 15th AI Update on worldTime 5453141, m_periodCounter: 1 15th AI Update on worldTime 5453171, m_periodCounter: 2 Repeating effect applied [+67 from decode] op272 applying on worldTime: 5453173, m_periodCounter: 0 15th AI Update on worldTime 5453201, m_periodCounter: 1 15th AI Update on worldTime 5453231, m_periodCounter: 2 Repeating effect applied [+60 from last apply] op272 applying on worldTime: 5453233, m_periodCounter: 0 15th AI Update on worldTime 5453261, m_periodCounter: 1 15th AI Update on worldTime 5453291, m_periodCounter: 2 Repeating effect applied [+60 from last apply] op272 applying on worldTime: 5453293, m_periodCounter: 0 15th AI Update on worldTime 5453321, m_periodCounter: 1 15th AI Update on worldTime 5453351, m_periodCounter: 2 Repeating effect applied [+60 from last apply] ...
And remember that pausing while op272 is active still double-counts a worldTime tick, causing additional problems.
-
It's complicated.
The general idea is that the persistent effects list is checked every 15 AI ticks. Spell duration works on "world time", and when you pause the game "world time" is reversed by 1 tick. So, you get a situation where a single "world time" tick is processed multiple times:
- worldTime increases to 1, everything in the game is processed.
- I pause the game, worldTime is reverted to 0, everything in the game is processed.
- I unpause the game, worldTime increases to 1, everything in the game is processed.
Oops, worldtime=1 was processed twice, which ticked the AI twice in a single "world time" tick... this is why pausing speeds up op272's next evaluation.
As for op272 happening multiple times in a single tick, I don't know. It's theoretically possible if the effects list is ticked 15+ times in a single update while the game is unpaused, but I have no idea what would cause that. Do you have an example?
And no, there's no way to fix the interval being inconsistent, it's a design flaw of the engine.
-
I also observe identical 104 stat distributions with a custom autoroller; it appears the rng breaks down at these extreme probabilities, though I can't tell you why.
-
1 hour ago, jastey said:
I'll be blunt: Is what @argent77 posted less save to use or would you strongly recommend using your EEx approach?
For this specific case argent's suggestion is more elegant. My solution is more generalized -- it should work for all symbol names and should continue to function even if a mod decided to go crazy with whitespace.
Edit: Argent's solution also needs to be tweaked slightly:
APPEND ~gtimes.ids~ ~3600 AJROM_TIMER~ UNLESS ~[ %TAB%]AJROM_TIMER%MNL%*$~
Without that %MNL%* WeiDU doesn't match the EOL anchor when Windows-style newlines are being used, (a source of much agony in the Discord).
-
Slightly overkill, but EEex uses something like this:
DEFINE_ACTION_FUNCTION B3_ESCAPE_STRING STR_VAR str = ~~ RET escaped_str BEGIN ACTION_DEFINE_ASSOCIATIVE_ARRAY to_escape BEGIN ~$~ => 1 ~^~ => 1 ~.~ => 1 ~*~ => 1 ~+~ => 1 ~?~ => 1 ~[~ => 1 ~]~ => 1 ~\~ => 1 END OUTER_PATCH_SAVE escaped_str ~%str%~ BEGIN limit = BUFFER_LENGTH FOR (i = 0; i < limit; ++i) BEGIN READ_ASCII i character (1) PATCH_IF VARIABLE_IS_SET EVAL ~to_escape_%character%~ BEGIN INSERT_BYTES i 1 WRITE_ASCII i ~\~ ++i ++limit END END END END DEFINE_ACTION_FUNCTION B3_APPEND_UNIQUE_IDS STR_VAR file_name = ~~ column_one = ~~ column_two = ~~ BEGIN LAF B3_ESCAPE_STRING STR_VAR str = EVAL ~%column_one%~ RET column_one_escaped = escaped_str END LAF B3_ESCAPE_STRING STR_VAR str = EVAL ~%column_two%~ RET column_two_escaped = escaped_str END APPEND ~%file_name%.IDS~ ~%column_one% %column_two%~ UNLESS ~^[ %TAB%]*%column_one_escaped%[ %TAB%]+%column_two_escaped%[ %TAB%]*%MNL%*$~ END
This appends an entry only if there isn't an exact match already present in the file, (barring whitespace). Used like:
LAF B3_APPEND_UNIQUE_IDS STR_VAR file_name = ~GTIMES~ column_one = ~3600~ column_two = ~AJROM_TIMER~ END LAF B3_APPEND_UNIQUE_IDS STR_VAR file_name = ~GTIMES~ column_one = ~3600~ column_two = ~C#AJROM_TIMER~ END
(I started writing this before argent commented so I'm still posting it)
-
I think a broken implementation shows clear intent, even if the description doesn't mention it.
-
Well, it works in my tests, and I've stepped through the game in a debugger to confirm that. Make sure you:
1) Are installing it on the latest IWD2 patch version, v2.01.
2) That the option is under the [Game Options] section.
3) That the INI value didn't get reset from last time.
4) That there's only one instance of Suppress Extra Difficulty Damage in the INI.
If it still isn't working, could you upload your INI for me to test.
-
You're right — the option's code is still in the engine, but the game immediately discards the INI value and sets it to 0. I've attached a mod that restores the INI option, though since it might have been intentionally disabled I don't know if it will cause problems.
-
Open icewind2.ini, add the following under the [Game Options] section:
Suppress Extra Difficulty Damage=1
-
...And since PROFICIENCY2WEAPON is what applies the penalties for dual-wielding, having a weapon created by op111 removes the thac0 penalties for dual-wielding all together.
@RoyalProtector The thac0 difference between your character's main-hand and off-hand are from the different enchantment levels of the weapons. Since BBoD is created by op111 Two-Weapon Style is completely ignored, including any penalties it would have otherwise applied.
-
1 hour ago, Luke said:
@Bubb Can you confirm op111 messes with Two-Weapon style even if BIT7 (Left-handed) and BIT13 (Forbid off-hand weapon) are both set to 0 in the ITM file at offset 0x18...?
There's an exception in the engine -- if PROFICIENCY2WEAPON is going to be applied and the currently-selected weapon is in SLOT_MISC19, apply PROFICIENCYSINGLEWEAPON instead.
[code] Code fixes, aka stuff we can't fix
in EE Fixpack
Posted
Here's a fun one I helped @morpheus562 investigate. Repo steps:
1) Blind a party member.
2) Kill them with Magic Missile.
Minor Bug: The game restores their visual range and reenables their ability to clear the FoW, even though they are dead.
Serious Bug: The area's character counter is now off — it thinks two party members died when only one did. If you then kill everyone but charname, the engine believes no characters exist in the area and forces the viewport to the master area. Charname becomes unselectable and the game is softlocked.