Jump to content

Help! Backstab Script causing Character to leave shadows


WizWom

Recommended Posts

I made up this script to automatically backstab, and it seems sweet... except that every time the character sees an enemy, it somehow causes him to leave shadows.

 

I can't even honestly debug what part is doing it, because it seems PauseGame() ALSO causes the character to leave shadows.

 

IF
HotKey(S)
Global("WXNoSneak","LOCALS",0)
THEN
RESPONSE #100
	SetGlobal("WXNoSneak","LOCALS",1)
END

IF
HotKey(S)
!Global("WXNoSneak","LOCALS",0)
THEN
RESPONSE #100
	SetGlobal("WXNoSneak","LOCALS",0)
	StartTimer(5,1)
END

IF
See(NearestEnemyOf(Myself))
Range(NearestEnemyOf(Myself),8)
THEN
RESPONSE #100
	SetGlobal("WxMelee","LOCALS",1)
	EquipMostDamagingMelee()
	Continue()
END

IF
!ModalState(STEALTH)
!See(NearestEnemyOf(Myself))
CombatCounter(0)
Global("WXNoSneak","LOCALS",0)
TimerExpired(5)
ActionListEmpty()
THEN
RESPONSE #100
	StartTimer(5,6)
	Hide()
END

IF
CombatCounter(0)
!See(NearestEnemyOf(Myself))
Global("WxMelee","LOCALS",0)
ActionListEmpty()
THEN
RESPONSE #100
	SetGlobal("WxMelee","LOCALS",1)
	EquipMostDamagingMelee()
	Continue()
END

IF
!See(NearestEnemyOf(Myself))
OR(7)
	Heard([ANYONE],99)
	Heard([ANYONE],ALERT)
	Heard([ANYONE],ASSIST)
	Heard([ANYONE],1)
	Heard([ANYONE],2)
	Heard([ANYONE],2727)
	Heard([ANYONE],50)
THEN
RESPONSE #100
	MoveToObject(LastHeardBy(Myself))
END

IF
CombatCounter(0)
!See(NearestEnemyOf(Myself))
!See([0.0.0.0.WXJON_TARGET])
!Detect([ENEMY])
THEN
RESPONSE #100
END

IF
OR(2)
	See(NearestEnemyOf(Myself))
	See([0.0.0.0.WXJON_TARGET])
!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
!StateCheck(Myself,STATE_IMPROVEDINVISIBILITY)
THEN
RESPONSE #100
	Shout(ALERT)
	Continue()
END

IF
CombatCounter(0)
!See(NearestEnemyOf(Myself))
Detect([ENEMY])
!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
!StateCheck(Myself,STATE_IMPROVEDINVISIBILITY)
THEN
RESPONSE #100
	Hide()
	MoveToObject(NearestEnemyOf(Myself))
END

IF
CombatCounter(0)
!See(NearestEnemyOf(Myself))
ActionListEmpty()
InMyArea(NearestEnemyOf(Myself))
!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
!StateCheck(Myself,STATE_IMPROVEDINVISIBILITY)
THEN
RESPONSE #100
	Hide()
END

IF
CombatCounter(0)
OR(2)
	See(NearestEnemyOfType([EVILCUTOFF]))
	See([0.0.0.0.WXJON_TARGET])
HPGT([EVILCUTOFF],1)
!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
!StateCheck(Myself,STATE_IMPROVEDINVISIBILITY)
THEN
RESPONSE #100
	StartCombatCounter()
	Shout(ALERT)
	SetGlobalTimer("WXHalfAttack","LOCALS",1)
	Continue()
END

IF
CombatCounter(0)
OR(2)
	Detect([EVILCUTOFF])
	Detect([0.0.0.0.WXJON_TARGET])
HPGT([EVILCUTOFF],1)
ModalState(STEALTH)
THEN
RESPONSE #100
	StartCombatCounter()
	SetGlobalTimer("WXHalfAttack","LOCALS",1)
	Continue()
END

IF
OR(2)
	See(NearestEnemyOf(Myself))
	See(Nearest([0.0.0.0.WXJON_TARGET]))
!Range(LastSeenBy(Myself),8)
!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
!StateCheck(Myself,STATE_IMPROVEDINVISIBILITY)
THEN
RESPONSE #100
	SetGlobal("WxMelee","LOCALS",0)
	EquipRanged()
	Continue()
END

IF
See(NearestEnemyOf(Myself))
OR(6)
	See(Nearest([0.0.0.0.WXJON_TARGET]))
	See(NearestEnemyOfType([ENEMY.0.0.CLERIC_ALL]))
	See(NearestEnemyOfType([ENEMY.0.0.BARD_ALL]))
	See(NearestEnemyOfType([ENEMY.0.0.DRUID_ALL]))
	See(NearestEnemyOfType([ENEMY.0.0.LONG_BOW]))
	See(NearestEnemyOf(Myself))
OR(3)
	ModalState(STEALTH)
	StateCheck(Myself,STATE_INVISIBLE)
	StateCheck(Myself,STATE_IMPROVEDINVISIBILITY)
!TargetUnreachable(LastSeenBy(Myself))
THEN
RESPONSE #100
	ActionOverride(LastSeenBy(Myself),DisplayStringHead(Myself,10070)) // Target
	ChangeSpecifics(LastSeenBy(Myself),WXJON_TARGET)
	EquipMostDamagingMelee()
	Continue()
END

IF
OR(3)
	ModalState(STEALTH)
	StateCheck(Myself,STATE_INVISIBLE)
	StateCheck(Myself,STATE_IMPROVEDINVISIBILITY)
See(Nearest([0.0.0.0.WXJON_TARGET]))
Class(LastSeenBy(Myself),INNOCENT)
THEN
RESPONSE #100
	ChangeSpecifics(LastSeenBy(Myself),0)
	Continue()
END

IF
OR(3)
	ModalState(STEALTH)
	StateCheck(Myself,STATE_INVISIBLE)
	StateCheck(Myself,STATE_IMPROVEDINVISIBILITY)
See(Nearest([0.0.0.0.WXJON_TARGET]))
!Range(LastSeenBy(Myself),2)
THEN
RESPONSE #100
	DisplayStringHead(LastSeenBy(Myself),12128) // Backstab Damage
	FollowObjectFormation(LastSeenBy(Myself),11,1)
END

IF
OR(3)
	ModalState(STEALTH)
	StateCheck(Myself,STATE_INVISIBLE)
	StateCheck(Myself,STATE_IMPROVEDINVISIBILITY)
See(Nearest([0.0.0.0.WXJON_TARGET]))
THEN
RESPONSE #100
	AttackNoSound(LastSeenBy(Myself))
END

IF
GlobalTimerNotExpired("WXHalfAttack","LOCALS")
See(NearestEnemyOf(Myself))
!Class(NearestEnemyOf(Myself),INNOCENT)
Allegiance(NearestEnemyOf(Myself),EVILCUTOFF)
THEN
RESPONSE #100
	Attack(NearestEnemyOf(Myself))
END

IF
See(NearestEnemyOf(Myself))
!Class(LastSeenBy(Myself),INNOCENT)
Allegiance(LastSeenBy(Myself),EVILCUTOFF)
THEN
RESPONSE #100
	Attack(LastSeenBy(Myself))
END

Link to comment

IF
See(NearestEnemyOf(Myself))
OR(6)
	See(Nearest([0.0.0.0.WXJON_TARGET]))
	See(NearestEnemyOfType([ENEMY.0.0.CLERIC_ALL]))
	See(NearestEnemyOfType([ENEMY.0.0.BARD_ALL]))
	See(NearestEnemyOfType([ENEMY.0.0.DRUID_ALL]))
	See(NearestEnemyOfType([ENEMY.0.0.LONG_BOW]))
	See(NearestEnemyOf(Myself))
OR(3)
	ModalState(STEALTH)
	StateCheck(Myself,STATE_INVISIBLE)
	StateCheck(Myself,STATE_IMPROVEDINVISIBILITY)
!TargetUnreachable(LastSeenBy(Myself))
THEN
RESPONSE #100
	ActionOverride(LastSeenBy(Myself),DisplayStringHead(Myself,10070)) // Target
	ChangeSpecifics(LastSeenBy(Myself),WXJON_TARGET)
	EquipMostDamagingMelee()
	Continue()
END

 

Actions EquipMostDamagingMelee() and Continue() break stealth action, as well as ChangeSpecifics(LastSeenBy(Myself),WXJON_TARGET), but you can change it to ActionOverride(LastSeenBy(Myself),ChangeSpecifics(Myself,WXJON_TARGET)).

 

IF
!ModalState(STEALTH)
!See(NearestEnemyOf(Myself))
CombatCounter(0)
Global("WXNoSneak","LOCALS",0)
TimerExpired(5)
ActionListEmpty()
THEN
RESPONSE #100
	StartTimer(5,6)
	Hide()
END

 

I would change !ModalState(STEALTH) to !StateCheck(Myself,STATE_INVISIBLE) and !See(NearestEnemyOf(Myself)) to !Detect(NearestEnemyOf(Myself)).

Your character will still try to hide with !ModalState(STEALTH), even if he drinks potion of invisibility.

With !See you will try to hide when invisible enemy is near to you.

 

StateCheck(Myself,STATE_IMPROVEDINVISIBILITY) returns true only when you are partially invisible (it means, that enemy can see you).

Replace

OR(3)
	ModalState(STEALTH)
	StateCheck(Myself,STATE_INVISIBLE)
	StateCheck(Myself,STATE_IMPROVEDINVISIBILITY)

with StateCheck(Myself,STATE_INVISIBLE) and

!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
!StateCheck(Myself,STATE_IMPROVEDINVISIBILITY)

with !StateCheck(Myself,STATE_INVISIBLE)

Link to comment
Actions EquipMostDamagingMelee() and Continue() break stealth action, as well as ChangeSpecifics(LastSeenBy(Myself),WXJON_TARGET), but you can change it to ActionOverride(LastSeenBy(Myself),ChangeSpecifics(Myself,WXJON_TARGET)).

[/code]

Continue()? Tested it, you are correct. Weird.

 

Also, it seems...

IF
CombatCounter(0)
OR(2)
	Detect([EVILCUTOFF])
	Detect([0.0.0.0.WXJON_TARGET])
HPGT([EVILCUTOFF],1)
OR(2)
	ModalState(STEALTH)
	StateCheck(Myself,STATE_INVISIBLE)
THEN
RESPONSE #100
	StartCombatCounter()
	ActionOverride(NearestEnemyOf(Myself),DisplayStringHead(Myself,52333)) // Beware!  More enemies approach!
	SetGlobalTimer("WXHalfAttack","LOCALS",1)
END

breaks stealth... must be the StartCombatCounter()

 

 

StateCheck(Myself,STATE_IMPROVEDINVISIBILITY) returns true only when you are partially invisible (it means, that enemy can see you).

Replace

OR(3)
	ModalState(STEALTH)
	StateCheck(Myself,STATE_INVISIBLE)
	StateCheck(Myself,STATE_IMPROVEDINVISIBILITY)

with StateCheck(Myself,STATE_INVISIBLE) and

 

Tried that, doesn't work at all when I'm in Stealth.

Link to comment

No, this is the ToB engine I'm working with. For Tutu, but it should be useful for any thief type under that engine.

Well, after working with the code a bit I and up with this functioning code:

IF
Global("WXSneakTime","LOCALS",0)
THEN
RESPONSE #100
	SetGlobalTimer("WXSneakTime","LOCALS",1)
END

IF
HotKey(S)
Global("WXNoSneak","LOCALS",0)
THEN
RESPONSE #100
	SetGlobal("WXNoSneak","LOCALS",1)
END

IF
HotKey(S)
!Global("WXNoSneak","LOCALS",0)
THEN
RESPONSE #100
	SetGlobal("WXNoSneak","LOCALS",0)
END

IF
!ModalState(STEALTH)
See(NearestEnemyOf(Myself))
Range(NearestEnemyOf(Myself),8)
THEN
RESPONSE #100
	SetGlobal("WxMelee","LOCALS",1)
	EquipMostDamagingMelee()
	Continue()
END

IF
!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
!LOS(NearestEnemyOf(Myself),14)
CombatCounter(0)
Global("WXNoSneak","LOCALS",0)
GlobalTimerExpired("WXSneakTime","LOCALS")
ActionListEmpty()
THEN
RESPONSE #100
	SetGlobalTimer("WXSneakTime","LOCALS",ONE_ROUND)
	Hide()
END

IF
CombatCounter(0)
!Detect(NearestEnemyOf(Myself))
Global("WxMelee","LOCALS",0)
ActionListEmpty()
THEN
RESPONSE #100
	SetGlobal("WxMelee","LOCALS",1)
	EquipMostDamagingMelee()
	Continue()
END

IF
!See(NearestEnemyOf(Myself))
OR(7)
	Heard([ANYONE],99)
	Heard([ANYONE],ALERT)
	Heard([ANYONE],ASSIST)
	Heard([ANYONE],1)
	Heard([ANYONE],2)
	Heard([ANYONE],2727)
	Heard([ANYONE],50)
THEN
RESPONSE #100
	MoveToObject(LastHeardBy(Myself))
END

IF
CombatCounter(0)
!Detect([0.0.0.0.WXJON_TARGET])
!Detect([ENEMY])
THEN
RESPONSE #100
END

IF
OR(2)
	See(NearestEnemyOf(Myself))
	See([0.0.0.0.WXJON_TARGET])
!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
THEN
RESPONSE #100
	DisplayStringHead(Myself,52333) // Beware!  More enemies approach!
	Shout(ALERT)
	Continue()
END

IF
CombatCounter(0)
Detect([ENEMY])
LOS(NearestEnemyOf(Myself),14)
!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
THEN
RESPONSE #100
	Hide()
	MoveToObject(NearestEnemyOf(Myself))
END

IF
CombatCounter(0)
!LOS(NearestEnemyOf(Myself),14)
ActionListEmpty()
InMyArea(NearestEnemyOf(Myself))
!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
THEN
RESPONSE #100
	Hide()
END

IF
CombatCounter(0)
OR(2)
	See(NearestEnemyOfType([EVILCUTOFF]))
	See(NearestMyGroupOfType([0.0.0.0.WXJON_TARGET]))
HPGT([EVILCUTOFF],1)
!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
THEN
RESPONSE #100
	StartCombatCounter()
	DisplayStringHead(Myself,52333) // Beware!  More enemies approach!
	Shout(ALERT)
	SetGlobalTimer("WXHalfAttack","LOCALS",1)
	Continue()
END

IF
OR(2)
	See(NearestEnemyOf(Myself))
	See(NearestMyGroupOfType([0.0.0.0.WXJON_TARGET]))
!Range(LastSeenBy(Myself),8)
!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
THEN
RESPONSE #100
	SetGlobal("WxMelee","LOCALS",0)
	EquipRanged()
	Continue()
END

IF
OR(5)
	See(NearestEnemyOfType([ENEMY.0.0.CLERIC_ALL]))
	See(NearestEnemyOfType([ENEMY.0.0.BARD_ALL]))
	See(NearestEnemyOfType([ENEMY.0.0.DRUID_ALL]))
	See(NearestEnemyOfType([ENEMY.0.0.LONG_BOW]))
	See(NearestEnemyOf(Myself))
OR(2)
	ModalState(STEALTH)
	StateCheck(Myself,STATE_INVISIBLE)
!TargetUnreachable(LastSeenBy(Myself))
!Specifics(LastSeenBy(Myself),WXJON_TARGET)
THEN
RESPONSE #100
	ActionOverride(LastSeenBy(Myself),DisplayStringHead(Myself,10070)) // Target
	ActionOverride(LastSeenBy(Myself),ChangeSpecifics(Myself,WXJON_TARGET))
END

IF
See([0.0.0.0.WXJON_TARGET])
Class(LastSeenBy(Myself),INNOCENT)
THEN
RESPONSE #100
	ChangeSpecifics(LastSeenBy(Myself),0)
END

IF
OR(2)
	ModalState(STEALTH)
	StateCheck(Myself,STATE_INVISIBLE)
See([0.0.0.0.WXJON_TARGET])
!Range(LastSeenBy(Myself),2)
THEN
RESPONSE #100
	ActionOverride(LastSeenBy(Myself),DisplayStringHead(Myself,12128)) // Backstab Damage
	FollowObjectFormation(LastSeenBy(Myself),11,1)
END

IF
OR(2)
	ModalState(STEALTH)
	StateCheck(Myself,STATE_INVISIBLE)
See([0.0.0.0.WXJON_TARGET])
Range(LastSeenBy(Myself),2)
THEN
RESPONSE #100
	EquipMostDamagingMelee()
	AttackNoSound(LastSeenBy(Myself))
END

IF
GlobalTimerNotExpired("WXHalfAttack","LOCALS")
See(NearestEnemyOf(Myself))
!Class(NearestEnemyOf(Myself),INNOCENT)
Allegiance(NearestEnemyOf(Myself),EVILCUTOFF)
!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
THEN
RESPONSE #100
	Attack(NearestEnemyOf(Myself))
END

IF
See(NearestEnemyOf(Myself))
!Class(LastSeenBy(Myself),INNOCENT)
Allegiance(LastSeenBy(Myself),EVILCUTOFF)
!ModalState(STEALTH)
!StateCheck(Myself,STATE_INVISIBLE)
THEN
RESPONSE #100
	Attack(LastSeenBy(Myself))
END

 

See(Nearest([0.0.0.0.WXJON_TARGET])) did not work where I have See([0.0.0.0.WXJON_TARGET]); it seems Nearest() is broken.

 

One of the reasons I want to arget net just NearestEnemyOfType() is because I use Specific WXJON_TARGET for NPC battles, it's a tweak, since it's set by Ajantis in my fix to allow Jonathan to join in his attacks on Evil party members he attacks.

 

But this use of specifics to track my backstab target without making a big nasty block is nice and sweet.

 

The only bug right now is if the character hits the range 2 check on the way to getting behind the target, then it won't end up backstabbing. I can't see any way to avoid that, though.

 

And I suppose the DisplayStringHeads are not needed anymore - but I like knowing what my characters are doing.

Link to comment
I have vague recollections of Horred mentioning that the IDS mask on Nearest() gets ignored.
Nearest() itself just doesn't work, but it's identical to just (O:Object) so doesn't matter much. EA isn't checked by the engine for NearestEnemy* and NearestMyGroup* (even though the latter doesn't have anything to do with EA). In general, it won't make a difference, but NearestEnemyOfType([EA]) is bad (See([EA]) will give you what you want). NearestMyGroupOfType() can detect only creatures with the same group (specifics) as the caller.

 

I wouldn't bother using LOS(); it's not guaranteed to do anything more useful than See() (if even that). InMyArea() could just as easily be Exists() (NearestEnemyOf() doesn't exist unless there's a living enemy within visual range that's visible to the caller). Detect(NearestEnemyOf()) is similarly useless (again, nearest living visible enemy). TargetUnreachable() does nothing.

Link to comment

I was under the impression that detect() would work out the the full VisualRange distance, See() just to the area cleared of Fog Of War by the active character. Also Detect() is supposed to continue to sense a creature you can hear but not see... such as one around a corner, or in darkness (not that the game uses Darkness)

 

So, all things being equal, if it might do a little more than See() it's worth using instead.

 

Re: ChangeSpecifics()... hrm, I'm going to have to survey the install and see what I can see. I suppose I could use SetToken() but that seemed more arcane.

I did want to figure out some way to tag the most dangerous opponent, then have the entire party attack it. I'm going to have to look at cierrek's Party AI scripts and see what he's doing.

Link to comment

I'm not sure what you're suggesting. LOS() is unused and I don't think we ever figured out anything about it. Detect() works only on a creature that would be visible were it not invisibile (i.e., you still have to be able to see it). Detect() won't do anything more than See() for dynamic object types -- these objects are determined separately as needed, and for the engine to consider an actor a valid NearestEnemyOf(), it has to be alive, within visual range of the caller, and actually visible to the caller. Outside a creature with the SEEINVISIBLE stat, NearestEnemyOf() will *never* be an invisible object (so Detect() will either pick up the nearest visible enemy or will return false (Detect(null))).

 

Specifics is group, and although it's used without much purpose in the game (usually as a way to determine a specific creature in targeting), it's best to avoid setting it generically to targets everywhere since it invalidates NearestMyGroup* and InMyGroup checks.

 

Objects See()n are retained by LastSeenBy(), so you could adopt a more advanced targeting block using False() triggers to funnel through the targeting sequence and wind up with an equivalent target to the current specifics shuffling.

Link to comment
Objects See()n are retained by LastSeenBy(), so you could adopt a more advanced targeting block using False() triggers to funnel through the targeting sequence and wind up with an equivalent target to the current specifics shuffling.

 

For this application, perhaps. Like I mentioned, the ultimate goal is to have some sort of party cohesion under AI rather than a lot of independent attacking.

 

I've run into a small trouble with this scripting: sometimes, the character will be involved in a discussion with an NPC, who then goes hostile. If the PC is stealthed, such a dialog kills stealth, which means I can't backstab the ne'er-de-well as he properly deserves - the scipt thinks he's not ModalState(STEALTH) anymore, even though he still is not visible. And I already mentioned StateCheck(Myself,STATE_INVISIBLE) doesn't apply to a stealthed character, didn't I?

Link to comment
For this application, perhaps. Like I mentioned, the ultimate goal is to have some sort of party cohesion under AI rather than a lot of independent attacking.

Umm.... see my sig? If the Party Co-operation Scripts don't do what you're after, feel free to rip them apart and use any code chunks that might help you. The targeting needs an overhaul (I might even do it one day!) but in general they 'll probably do what you're after. Alternatively, just ask and I'll email you the snippets that are used to construct the final scripts.

 

-Y-

Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...