Jump to content

Small 34.3 bugs I didn't see mentioned yet


Recommended Posts

  • The general AI doesn't get a block for Potion of Invulnerability (POTN11), despite them predominantly being assigned to warrior ethoses. This leads to lots of them lying around on the floor unused after a fight.
  • GROMG09 and GORSTA07 are Thieves with their kit set to Berserker (vanilla). This causes SCS to assign them Berserker AI instead of Thief AI. GROMG09 has some invisibility potions he'll never use because of this.
    • GORSTA07 could be given some invisibility scrolls or something.
  • Small Spell Revisions compatibility problems.
    • Smart enemies do enemy alignment checks when deciding to cast Smite/Blight and (U)HW. These spells aren't alignment-specific in SR.
    • SR attempts to limit op16/op317, eradicating it from common sources, which conflicts with SCS's haste detection.
      • If this change is extended to the Oil of Speed via Item Revisions, enemies will apply them repeatedly as they have no way to detect that they're already hasted.
Edited by Person
Link to comment
2 hours ago, Person said:

The general AI doesn't get a block for Potion of Invulnerability (POTN11), despite them predominantly being assigned to warrior ethoses. This leads to lots of them lying around on the floor unused after a fight.

Checking potionuse.ssl in the genai folder...

/////////////////////////////////////////////////////
////	If you've got a defence potion, take it right
////	away. For crude convenience, we just use a 
////	global to record if we've done so.
////
////	This is for L14+characters.
/////////////////////////////////////////////////////

IF TRIGGER
        IgnoreBlock(IsMoron)
        TriggerBlock(CorePlus)
	See(NearestEnemyOf(Myself))
	!StateCheck(Myself,STATE_INVISIBLE)
	!Global("takendefence","LOCALS",1)
	CheckStatGT(Myself,13,Level)
THEN DO
	Action(Potion,"dw#ptn34",@101034)
	Action(Potion,"dw#ptn35",@101035)
	Action(Potion,"dw#ptn21",@101021)
	Action(Potion,"dw#ptn45",@101045)
	Action(Potion,"%tutu_var%potn34",@101034)
	Action(Potion,"%tutu_var%potn35",@101035)
	Action(Potion,"%tutu_var%potn21",@101021)
	Action(Potion,"%tutu_var%potn45",@101045)
	SetGlobal("takendefence","LOCALS",1)
END

///////////////////////////////////////////////////////////////
///	Failing that, take potions of Power or Heroism. 
///	We use a counter to see if he's taken one already
/////////////////////////////////////////////////////////////////////

IF TRIGGER
        IgnoreBlock(IsMoron)
        TriggerBlock(CorePlus)
  See(NearestEnemyOf(Myself))
!StateCheck(Myself,STATE_INVISIBLE)
 Global("heroptn","LOCALS",0)
  Range(NearestEnemyOf(Myself),5)
THEN DO
    SetGlobal("heroptn","LOCALS",1)
	Action(Potion,"dw#ptn41",@101041)
	Action(Potion,"%tutu_var%potn41",@101041)
	Action(Potion,"dw#ptn09",@101009)
	Action(Potion,"%tutu_var%potn09",@101009)
END

////////////////////////////////////////////////////
////	Finally, a few misc. potions
/////////////////////////////////////////////////////

IF TRIGGER
        IgnoreBlock(IsMoron)
        TriggerBlock(CorePlus)
	See(NearestEnemyOf(Myself))
	!StateCheck(Myself,STATE_INVISIBLE)
THEN DO
	ActionCondition(Potion,"dw#ptn24",@101024;CheckStatGT(Myself,0,ARMORCLASS))
	ActionCondition(Potion,"%tutu_var%potn24",@101024;CheckStatGT(Myself,0,ARMORCLASS))		
	ActionCondition(Potion,"dw#ptn28",@101028;CheckStatLT(Myself,15,CON))
	ActionCondition(Potion,"%tutu_var%potn28",@101028;CheckStatLT(Myself,15,CON))
	Action(Potion,"dw#ptn42",@101042)
	Action(Potion,"%tutu_var%potn42",@101042)
END

The first of those three blocks does potions of clarity, magic protection, magic shielding, and freedom. The third does potions of defense, fortitude, and regeneration. Clearly, potions of invulnerability should be used somewhere in here.

Now, as to when the SCS potion component assigns invulnerability potions... checking potion/potion_shared.tpa ...

The functions here assign potions based on groupings with similar function. Potions of invulnerability belong to four of those groupings: protectionmage, protection1, protection2, protection3. The protectionmage group consists only of potions of invulnerability and defense, and is used for BG1 enemies of level >= 7 that are neither single-class warriors nor single-class thieves. The other three "protection" groups are given to enemies of sufficient level (threshold depending on game) that are single-class warriors or thieves.

So, there's another issue here: the potion component regularly assigns invulnerability potions to creatures that shouldn't be able to use them. There just aren't enough class checks in that component. (Monks shouldn't get oils of speed either.)

Link to comment
On 5/2/2023 at 8:49 PM, Person said:

The general AI doesn't get a block for Potion of Invulnerability (POTN11), despite them predominantly being assigned to warrior ethoses. This leads to lots of them lying around on the floor unused after a fight.

Fixed (also the allocation issues caught by jmerry)

 

On 5/2/2023 at 8:49 PM, Person said:

GROMG09 and GORSTA07 are Thieves with their kit set to Berserker (vanilla). This causes SCS to assign them Berserker AI instead of Thief AI. GROMG09 has some invisibility potions he'll never use because of this.

  • GORSTA07 could be given some invisibility scrolls or something.

 

Fixed for GROMG09. GORSTA07 is an unkitted fighter on my install.

 

On 5/2/2023 at 8:49 PM, Person said:

Small Spell Revisions compatibility problems.

  • Smart enemies do enemy alignment checks when deciding to cast Smite/Blight and (U)HW. These spells aren't alignment-specific in SR.
  • SR attempts to limit op16/op317, eradicating it from common sources, which conflicts with SCS's haste detection.
    • If this change is extended to the Oil of Speed via Item Revisions, enemies will apply them repeatedly as they have no way to detect that they're already hasted.

 

I've fixed the Holy/Unholy issue. Detecting Haste, if it doesn't set the STATE_HASTED marker, is a bit beyond me, at least for the next release.

Link to comment
8 hours ago, DavidW said:

I've fixed the Holy/Unholy issue. Detecting Haste, if it doesn't set the STATE_HASTED marker, is a bit beyond me, at least for the next release.

Isn't this one more a Spell Revisions issue than an SCS issue anyway? It's one thing to nerf 3rd level Haste to single target but another entirely to strip the opcode from it for the minor benefit of not accelerating poison/disease/regeneration from items (regeneration from spells is handled easily).

Even in vanilla there are script checks for STATE_HASTED.

Welcome back Btw.

ETA. A couple of other players noticed that conjurers can't effectively use anti-magic in current SCS + SR

Edited by polytope
Link to comment
12 hours ago, polytope said:

one thing to nerf 3rd level Haste to single target but another entirely to strip the opcode from it

SR has removed the Haste opcode in favor of movement + APR bonuses for like 10 years. May be suboptimal in some ways but it is a very settled, longstanding change. 

Given that SR is still being worked on (several PRs have been accepted recently IIRC - I’m not around much but I think I saw some notifications), we could fairly easily implement a spellstate or something if it would help SCS.  

(And in my current install with SR v4b19, Haste is party-wide, it uses the INAREAPA projectile.)

Link to comment

Putting aside the design question of whether SR should be removing Haste (my strong instinct is 'no', at least not without taking seriously the responsibility to sort out scripting, since STATE_HASTED is checked for nearly 200 times in the unmodded game) I've worked around this (more or less) for SCS.

Link to comment
13 hours ago, subtledoctor said:

SR has removed the Haste opcode in favor of movement + APR bonuses for like 10 years. May be suboptimal in some ways but it is a very settled, longstanding change.

It genuinely breaks several vanilla game scripts, because some creatures employ Haste as a spell like ability, rather than having it memorized.

From MELISS01.bcs

IF
	!Allegiance(LastSeenBy(Myself),GOODCUTOFF)
	!See([GOODCUTOFF])
	See([EVILCUTOFF])
	!StateCheck([EVILCUTOFF],STATE_HASTED)
	!GlobalTimerNotExpired("MelissanHaste","LOCALS")
THEN
	RESPONSE #100
		SetGlobalTimer("MelissanHaste","LOCALS",THREE_ROUNDS)
		ForceSpell([EVILCUTOFF],WIZARD_HASTE)  // SPWI305.SPL (Haste)
END

Gets into a useless endless loop trying to haste a monster which will of course never be hasted if opcode #16 is stripped from haste.

13 hours ago, subtledoctor said:

(And in my current install with SR v4b19, Haste is party-wide, it uses the INAREAPA projectile.)

That was my point, in earlier SR versions 3rd level Haste was single target, which is fine, that would be a reasonable nerf of a too-powerful 3rd level spell and doesn't cause the AI problems. The problem arises when the opcode itself is changed, not only for vanilla and SCS but for every other mod that introduces new AI scripts and assumes Haste has an associated detectable state.

Edited by polytope
Link to comment
4 hours ago, polytope said:

breaks several vanilla game scripts,

I’m not denying what you say, I’m just saying this would have been a great conversation to have with Demivrgvs in 2012. 

4 hours ago, polytope said:

in earlier SR versions 3rd level Haste was single target, which is fine, that would be a reasonable nerf of a too-powerful 3rd level spell and doesn't cause the AI problems.

Versions with single-target Haste also did not use the Haste opcode, IIRC. Heck, this might go back to SRv3. I haven’t looked at those files in a long time but I recall Demi talking about not using the busted Haste opcode since, like, forever. 

Link to comment

Or, can STATE_HASTED be spoofed/applied alongside the spell’s other effects?

This conversation is useful and I think it is certainly worth a discussion on the SR forum on whether to revert SR to using opcode 16. Especially since this led me to look up the opcode in the IESDP and learn for the first time that there is a “weak haste” parameter that SR could use. Worth a dedicated thread over there, and I will now stop diverting attention from DavidW’s other SCS business here.

Link to comment
43 minutes ago, Salk said:

Question about SR's haste opcode replacement: can't a workaround be used at script level?

Sure, you can parse and replace scripts at install time, but what about subsequently installed mods coming after Spell Revisions? SCS makes allowances, others might not.

29 minutes ago, subtledoctor said:

This conversation is useful and I think it is certainly worth a discussion on the SR forum on whether to revert SR to using opcode 16. Especially since this led me to look up the opcode in the IESDP and learn for the first time that there is a “weak haste” parameter that SR could use.

Weak haste opcode #16 type 2 just ensures APR are rounded up to the nearest whole number, it will not work well with fractional APR bonuses for this reason (although can only reach 5 attacks per round, type 0 haste allows up to 6) and still doubles the rate at which timed effects tick (as I've said, I think it's easier to work around unwanted doubling of frequencies of in game effects than the scripts that check for hasted states). #317 allows the same types, but is used in vanilla almost exclusively as type 1 - equivalent to Improved Haste.

Link to comment

For Enhanced Powergaming Scripts, I personally start with two base sets of scripts: 1) Vanilla base 2) SR Base. SR simply introduces too many changes to be worth patching existing vanilla scripts and its easier to just build it from scratch. I then manually add the spell state back to the SR version of haste within my initialize file:
 

///////////////////////////////////////////////////////////////////////////
// Create Spell State for Haste                                          //
///////////////////////////////////////////////////////////////////////////
	ACTION_IF (FILE_CONTAINS_EVALUATED (~splstate.ids~ ~HASTE~)) BEGIN
	  COPY_EXISTING ~splstate.ids~ ~override~
		COUNT_2DA_COLS cols
		READ_2DA_ENTRIES_NOW rows cols
		FOR (row = 1; row < rows; ++row) BEGIN
		  READ_2DA_ENTRY_FORMER rows row 1 ~state_name~
		  READ_2DA_ENTRY_FORMER rows row 0 ~state_ind~
		  PATCH_IF (~%state_name%~ STRING_EQUAL_CASE ~HASTE~) BEGIN
			SET haste = %state_ind%
		  END
		END
	  BUT_ONLY
	END

	ACTION_IF !(VARIABLE_IS_SET %haste%) BEGIN
		LAF ds_sort_ids STR_VAR ids=splstate END
		LAF d5_resolve_state STR_VAR new_state_id = ~HASTE~ RET new_state_ind END
		OUTER_SET haste = %new_state_ind%
	END
    
    LAF RES_NUM_OF_SPELL_NAME STR_VAR spell_name = ~WIZARD_HASTE~ RET spell_res END
	COPY_EXISTING ~%spell_res%.SPL~ ~override~ 
	  LPF CLONE_EFFECT INT_VAR match_opcode = 1 opcode = 328 parameter2 = %haste% special = 1 END

There are many spells within SR that I need to go back through and either add net new spellstates or reintroduce existing ones to ensure everything tracks correctly within Enhanced Powergaming Scripts. When it comes to Tactics Remix, I have not even looked at making it SR compatible at this time because that is going to be a huge amount of time to make work.

Edited by morpheus562
Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...