Larian Banner: Baldur's Gate Patch 9
Previous Thread
Next Thread
Print Thread
Joined: Dec 2015
stranger
OP Offline
stranger
Joined: Dec 2015
CharacterGetStat (OUT FLOAT statValue, CHARACTER character, CHARACTERSTAT statType)

Looks pretty self-explanatory, but for the life of me I can't seem to get it to output the value of any stat. Nothing seems to work for characterstat.

So I'm at a bit of a loss here as far as modding goes with the Enhanced Edition. Specifically with how CharacterGetStat() functions. I've been trying to get it to return _Char's Level, but it always seems to return 0.

The long and short of it is that I've attached this bit of code to NPCs and gotten it to fire off any time they take damage but because I can't get CharacterGetStat() to return the value of Level it fires off incorrectly on the first IF statement when somebody level 7 hits it.

[spoiler]
[code]
EVENT OnHitEffect
VARS
CHARACTER:_Char
FLOAT:_Level
ON
OnDamage(_,_,_Char,_)
ACTIONS
CharacterGetStat(_Level, _Char, Level) // Refuses to return any value other than 0. Level, Strength, Intelligence, ActPart nothing works.
CharacterHeal(_Char, _Level) // Always heals for 0% health because CharacterGetStat() always returns 0 for some reason.

IF "c1|c2" // Fires off incorrectly because Level == 0 when Level /should/ equal 7.
IsLessThen(_Level, 5)
IsEqual(_Level, 5)
THEN
CharacterConsume(__Me, damageTestOne)
ELIF "c1&(c2|c3)" // Never actually triggers due to CharacterGetStat() returning Level as 0
IsGreaterThen(_Level, 5)
IsLessThen(_Level, 10)
IsEqual(_Level, 10)
THEN
CharacterConsume(__Me, damageTestTwo)
ENDIF
[/code]
[/spoiler]

I've also been having to use CharacterHeal() as a makeshift debug log in-game to see when things fire off because I can't get DisplayText(), DisplayCombatInfoText(), StatusText(), DebugText(), or CombatLogText() to function correctly.

Any possible insight into how to use those properly or a better way to get some kind of log to debug these things would be fantastic if possible.

Last edited by Aria Boop; 02/12/15 06:40 PM.
Joined: Jul 2014
R
addict
Offline
addict
R
Joined: Jul 2014
Is "Level" the actual name of the CHARACTERSTAT? It's the only thing I can see that might be the issue after a quick glance at your code.

Joined: Jun 2013
old hand
Offline
old hand
Joined: Jun 2013
Shouldn't CharacterGetStat be under the IF? It's not an action.

I don't think you can directly check level either, whatever the name is. You could check Experience though.


Took a stab at it:

Code
EVENT OnHitEffect
VARS
CHARACTER:_Char
FLOAT:_Level
ON
OnDamage(_,_,_Char,_)
ACTIONS
//CharacterHeal(_Char, _Level) //not sure what this is for?
IF "c1&(c2|c3)"
CharacterGetStat(_Level, _Char, Experience)
IsLessThen(_Level, 40000)
IsEqual(_Level, 40000)
THEN
CharacterConsume(__Me, damageTestOne)
ELIF "c1&(c2|c3)" // Never actually triggers due to CharacterGetStat() returning Level as 0
IsGreaterThen(_Level, 40000)
IsLessThen(_Level, 330000)
IsEqual(_Level, 330000)
THEN
CharacterConsume(__Me, damageTestTwo)
ENDIF


My script-fu is still mediocre so ¯\_(ツ)_/¯

Last edited by SniperHF; 02/12/15 07:34 PM.
Joined: Aug 2014
old hand
Offline
old hand
Joined: Aug 2014
Try "AirResistance" as a stat, because that's definitely a character stat. If that doesn't work, has to be a structural thing. Maybe put the CharacterGetStat part in the IF statement instead of the action part?

Ninjaaaaad

Also, what exactly are you going for? For the enemy to heal on taking damage? Or is this just a test script?

Last edited by Baardvark; 02/12/15 07:37 PM.
Joined: Dec 2015
stranger
OP Offline
stranger
Joined: Dec 2015
Originally Posted by SniperHF
Shouldn't CharacterGetStat be under the IF? It's not an action.
I don't think you can directly check level either, whatever the name is. You could check Experience though.


I'm not sure it would work as an IF check considering CharacterGerStat() shouldn't return a boolean value, but I could be wrong. I'll have to give it a shot.

It should be checking what _Char's Level is and then setting the local variable _Level to that float.

Originally Posted by Rhidian
Is "Level" the actual name of the CHARACTERSTAT? It's the only thing I can see that might be the issue after a quick glance at your code.

I have no idea, actually. I've tried a bunch of things. Level, Strength, Intelligence, Act, ActPart, etc. They all return a value of 0.

Wasn't able to find a list of possible values for the stats anywhere except the Modifiers.txt under the modifier type "Character" entry and none of those seem to work either.

Originally Posted by Baardvark

Also, what exactly are you going for? For the enemy to heal on taking damage? Or is this just a test script?

My girlfriend and I got a bit inspired by your work with Scales and adding the telekinesis skills so we started playing around with the system to try and create some interesting depth with stances.

It's just a test script for now to try to see if certain OnHit abilities can be created.

The big picture was to have new Stances that improve in function for each turn you have them active. Self-escalating buffs that, in this instance, provide large damage bonuses but also large defense/resist negatives. (Turn 1 improves damage by 5%, crit by 3% but also gives -10% to all resistances. Turn 2 improves on this, bigger damage increase and resist decrease, etc.) We were trying create berserker type stances.

Overall this was pretty easy to achieve by writing a quick state machine to check against things like CharacterHasStatus(__Me, STANCE, Boost_ThrillOfBattle) and then CharacterConsume each new buff to override the previous as long as __ME had the Thrill of Battle stance toggled on.

But then we got to thinking that by turn 4 increasing/decreasing stats isn't really... interesting. That's where the test script comes into play. We created some on hit events that trigger OnDamage(_,_,_Char,_) and cause the NPC to consume a damaging effect to basically act as bonus damage or effects. Basically, by turn 4 any time a player with Thrill of Battle's fourth buff hit an NPC, the NPC would consume a self-damage potion for additional damage and by turn 5 the player had a 30% chance to self-heal for 5%.

This all works just fine, so we took it a step further and that's where we've hit this snag.

We were trying to create a range of scaling damage effects based on level. Something like:
Code
OnDamage
If (_playerLevel <= 5)
    Consume DamageRank1
Else if (_playerLevel >= 6)
    Consume DamageRank2


And that's where the snag shows up. CharacterGetStat only returns a value of 0 when passed the Level parameter. Not sure if we're using CharacterGetStat incorrectly or we're passing the incorrect parameter for CHARACTERSTAT and I wasn't able to find a list of valid parameters for it at all.

... Ahaha.. ha.. Bit of a long post, sorry.

Edit:
Originally Posted by SniperHF

//CharacterHeal(_Char, _Level) //not sure what this is for?

I've been using the CharacterHeal() function as a debug log of sorts so I can see when things fire off or not and to check the value of a float since I can't get any of the text display functions to work correctly either, haha.

Edit2:
Just tried using CharacterGetStat() in an IF and only seems to returns "True" and not a value or any kind of function like "if _float == characterstat", so I'm not sure how it could be used like that.

Also tried checking using AirResistance and "AirResistance" under ACTIONS, neither parameter works and returns a value of 0 when it should have been 39 or perhaps 0.39. Neither pass an IsGreaterThen(_stat, 1) or IsGreaterThen(_stat, 0.1) IF check.


Scrolled up and took a look at SniperHF's code and it totally works.

Using a Level 11 character:
Code
	IF "c1&(c2|c3)"
		CharacterGetStat(_Level, _Char, Level)
		IsLessThen(_Level, 10)
		IsEqual(_Level, 10)
	THEN
		CharacterHeal(_Char, 1)
	ELIF "c1&c2"
		CharacterGetStat(_Level, _Char, Level)
		IsGreaterThen(_Level, 10)
	THEN
		CharacterHeal(_Char, 10)
	ENDIF

So yeah, apparently it needs to be put under an IF block in conjunction with further checks apparently. Weird.

Mystery solved though, even passing the Level parameter works fine and fires off the ELIF correctly. This opens up quite a bit of range for things we're trying to implement now.

Thanks for all the help. =)

Last edited by Aria Boop; 02/12/15 10:03 PM.
Joined: Aug 2014
old hand
Offline
old hand
Joined: Aug 2014
Ha, well, I'm glad Scales has inspired you. There's really a lot of modding potential for adding new skills and whatnot. A berserker stance sounds awesome. Would love to integrate that into Scales with your credit, though of course if you want to keep it your own thing that's fine.

Edit: Ah, looks like it got solved, nevermind. I'll leave this here for reference anyway.

So if you look at the POTION_CON_POTION_Air_Res_A charscript, here's how they use "CharacterGetStat" (just posted the whole script since it's short.) It's in the IF statement, and I also see it used in the IF statement (with weight) for the mine itemscript. So I'd definitely put it in the IF statement, but otherwise I don't quite understand why it wouldn't work for you.

#TEMPLATE "_POTION_Base" : CON_Potion_Air_Res_A

INIT
CHARACTER:__Me
// [GLOBAL_VARS]
// [~GLOBAL_VARS]

EVENTS

// [EVENTS]
// [~EVENTS]

// Calculate the priority of the skill
EVENT CalculateScore_CON_Potion_Air_Res_A
VARS
// [CALC_VARS]
FLOAT:_StatAirResistance
FLOAT:_Score
// [~CALC_VARS]
ON
OnFunction("CalculateScore_CON_Potion_Air_Res_A")
ACTIONS
// [CALC_ACTIONS_PRE]
Set(_Score, 0.0)
// [~CALC_ACTIONS_PRE]
// [CALC_ACTIONS]
IF "((c1)|c2)&(!(c3&c4))"
CharacterHasBeenHitBy(__Me, Air) // c1
CharacterHasHadStatus(__Me, STUNNED) // c2
CharacterGetStat(_StatAirResistance, __Me, AirResistance) // c3
IsGreaterThen(_StatAirResistance, 50) // c4
THEN
Add(_Score, %ActionScore_CON_Potion_Air_Res_A)
ENDIF
// [~CALC_ACTIONS]

Cast(%ActionScore_CON_Potion_Air_Res_A, _Score)


Last edited by Baardvark; 02/12/15 09:59 PM.
Joined: Dec 2015
stranger
OP Offline
stranger
Joined: Dec 2015
Originally Posted by Baardvark
Would love to integrate that into Scales with your credit, though of course if you want to keep it your own thing that's fine.

I'd totally be okay with that.

We're pretty big on the idea of risk vs reward gameplay and the two stances we were implementing were the berserker stance and a staunch defender type of stance.

Heavy mitigation, improved taunt, looking at trying to implement counterattacks, and so on.

One thing that I was kind of bummed about with Original Sin was the lack of evasion and unarmed combat, basically a monk type of option.

Getting the OnHit effects for scaling level ranges working really helps with possibly implementing that since unarmed combat doesn't really work naturally.

Joined: Aug 2014
old hand
Offline
old hand
Joined: Aug 2014
Great! Looking forward to seeing what you do. Unarmed/monk characters are pretty hard to pull off. Hard to balance with no weapon stats, and what niche would they fill? They seem pretty redundant with rogues and dual-wield warriors. Maybe a mobile, slightly tanky CC-focused melee character, but that's still stepping on warrior and rogue's toes. Rogue needs to find his place before a monk joins the fray, though I think buffing the nasty deeds will help a lot with that.

What charscript are you adding your code to for the player abilities?

Joined: Jun 2013
old hand
Offline
old hand
Joined: Jun 2013
Originally Posted by Aria Boop

Scrolled up and took a look at SniperHF's code and it totally works.

Using a Level 11 character:
Code
	IF "c1&(c2|c3)"
		CharacterGetStat(_Level, _Char, Level)
		IsLessThen(_Level, 10)
		IsEqual(_Level, 10)
	THEN
		CharacterHeal(_Char, 1)
	ELIF "c1&c2"
		CharacterGetStat(_Level, _Char, Level)
		IsGreaterThen(_Level, 10)
	THEN
		CharacterHeal(_Char, 10)
	ENDIF




So level does work? That's interesting. In the old version it throws an error, I checked after you made the thread.


Quote
So yeah, apparently it needs to be put under an IF block in conjunction with further checks apparently. Weird.


A lot of their scripts work this way. Since I'm a know nothing scripter I just monkey see monkey do everything horsey

Last edited by SniperHF; 03/12/15 01:03 AM.
Joined: Dec 2015
stranger
OP Offline
stranger
Joined: Dec 2015
Originally Posted by SniperHF

A lot of their scripts work this way.


It's been a weird ride learning the syntax and how it all functions. It wasn't clicking for me that CharacterGetStat() was required to be in an IF block because returned a variable, haha. Programming habits getting in the way, I guess.

Originally Posted by Baardvark

What charscript are you adding your code to for the player abilities?


Hooking directly Player.charScript and adding:
Code
#INCLUDE Base
#INCLUDE Player_StateManager

INIT

USING Base
USING Player_StateManager

EVENTS

This lets me create separate scripts like a state machine to inherit and call from for each player. From there a whole lot can be influenced using On triggers like OnCombat(), OnTurn(), OnTurnEnded(), or even OnDamage(_,_,_,_).

For NPCs I've done the same thing by hooking into DefaultCharacter.charScript.

This way an event can be run on any NPC that receives damage via Damage(_,_,_Char,_) and you can run CharacterHasStatus(_Char, CONSUME, someKindOfCustomBoost) to check if they should do something like simulating an "on hit" effect that would be caused by a buff without having to rely on directly enchanting a weapon.


Joined: Aug 2014
old hand
Offline
old hand
Joined: Aug 2014
Neato. Looking forward to what you make.


Link Copied to Clipboard
Powered by UBB.threads™ PHP Forum Software 7.7.5