[BETA] Oblivion Script Extender (OBSE) v0020

Post » Sat Sep 04, 2010 1:20 am

I see. I don't think it's necessary to be able to write any field of the mod, some basic one would be sufficient for starters. I really hope someone will create this!
User avatar
Jerry Cox
 
Posts: 3409
Joined: Wed Oct 10, 2007 1:21 pm

Post » Fri Sep 03, 2010 8:46 pm

Something that seems to be v20 related:

I load a clean save and, after a few seconds, my quests kick in.
A couple of frames after that, the game spontaneously overwrites the last save.
It happens about 25% of the time (loading exactly the same save over and over)

After some investigation I found that my shortcut key mod has a shortcut for overwriting the most recent save. The code checks "if IsKeyPressed2 ".
Since I have not assigned a key for the overwrite function, the variable is zero.

So, it seems v20 does something that triggers the IsKeyPressed2 with a zero keycode argument.

Additional info:
The shortcut key mod is an old one (esp filedate: 2008) and I use it all the time since.
Did not happen with v19b after loading the same save about a dozen times.
On one of the runs during debug, GetCurrentFrameIndex went back by one, exactly when the glitch happened (one fame returned 4, the next returned 3). May be a coincidence, but I've never seen this happen before.

(I am deactivating the overwrite function, so I don't need a fix for that for a while. Well . . supposing it is an OBSE bug. )
User avatar
Chloe Botham
 
Posts: 3537
Joined: Wed Aug 30, 2006 12:11 am

Post » Sat Sep 04, 2010 1:01 am

Uuhm no, that doesn't do what I want at all, changing INI settings is something completely different from saving the data of dynamically placed references in a .esp file.

Umm, you can create your own values and not interfere with any other settings in the INI file... If I'm not mistaken that saves the values in .ini. Not the master ini file. As for storing ref's, can't, period, savegame only. References are stored by their base object ID and their "changes" in a savegame, this way if a mod is added/removed, the references on a load are loaded from base and the changes reapplied to it. This is why you can edit a race, save, reload a game and the changes are instant. Also references to any item are always different on each load. Storing a static ref outside of the savegame will not be valid, period. Storing values is fine outside of the game, strings, numbers, etc, but refs to objects is script crash-worthy. Say you store a ref thats F102385B, which is a creature. Reloading the savegame, that creature's original ref will not be that anymore because previous creatures loaded in before that one, won't have loaded first because you're in the cell with it before the others, plus you added a mod or 2 between the save, so the new ref could be F302384A which could point to nothing (script/engine crash) or something you didn't want.



Why not walk through all the potential targets in the target list, and do a GetCombatTarget check to the actor? Then you have everyone who is attacking the actor. You could alternately iterate over all the actors/creatures in the surrounding cells with GetFirstRef and GetNextRef, just in case the actor hasn't detected everyone that is attacking him yet.

I either misunderstand you, or you have an incorrect interpretation of GetCombatTarget. "If ActorB.GetCombatTarget == ActorA" does tell you if ActorA is currently being attacked by ActorB.

Again, "Potential" targets are not "active" enemies. GetCombatTarget only returns the active target the actor is directly fighting with, not everyone it's fighting with:

EG:

Actor A and B are evil.
Actor C, D, E and F are guards.
Actor A fights Actor C, actor B fights Actor D, while E and F back up and use arrows, E hits B while F also hits B.

According to how the combat system works, both A and B are in battle with C, D, E and F. When one dies, they go onto the next enemy automatically until combat ends. ActorA.GetCombatTarget will never show Actor E or Actor F until one of them actively targets Actor A directly, then it's a crapshoot to see who shows up, since ActorB.GetCombatTarget will not list E or F until D dies and it may not because C could be next on the enemies to attack if it's still alive.

Another instance:

Actor A and Bear are good.
A dozen Zombies ... BAD.
Actor A starts hacking at a zombie while Bear goes to attack another.
Actor A moves because it was getting mobbed (to death) by zombies.
Bear finishes killing it's zombie and turns to look for the closest enemy ATTACKING Actor A, sadly, it could pick the wrong one. Player is Actor A. Player.GetCombatTarget returns Null, always... So there's no way to tell who the player is attacking, but the Bear could look at all the actors in the area for a GetCombatTarget. But say a guard came to help Actor A and half the zombies are after him for a minute, it isn't presuming to say that if that guard dies they won't turn on the Actor A (Player) again. But Bear does a Zombie.GetIsAttacking ActorA will return a 1 *if* at some point that zombie will attack Actor A. The Bear can then find the closest one to Actor A that wants to harm it at some point and attack it. There is nothing currently to determine who's attacking an actor except for actively. GetCombatTarget returns the Current Active target, the one the actor is actually hitting.

I don't know if it's possible with OBSE proper (don't know if the game executable has support for writing mods, and if it doesn't, I don't imagine the OBSE team wants to write such support from scratch), but it's definitely possible if an OBSE plugin is written based off of CBash. Most of the work would be to expose the current API as function commands...you'd have support for reading/writing any field of any mod. It's been on the back of my mind to do once CBash reaches 1.0, but anyone is welcome to take a stab at it.

Again, the downside with this is as I stated above, the way the game reloads the savegame data, would destroy any externally loaded ref's. It wouldn't even work with static 1 base object refs, as any mods added/removed from the load order would again cause grief. It's simply not something thats going to be easy to do, unless the game's loading is patched to load your ref in before it re-creates them, as part of the load process, then possibly. But that's a massive undertaking I doubt OBSE is aimed at.

GuruSR.
User avatar
IsAiah AkA figgy
 
Posts: 3398
Joined: Tue Oct 09, 2007 7:43 am

Post » Fri Sep 03, 2010 8:54 pm

By saving it in an esp it is no longer treated as a saved record, but treated as any other mod. The script writer would have to take care to preserve formIDs, etc, but that's on them.

If you would like to continue this topic, please take it to a new thread. I don't think it needs to be cluttering this thread.
User avatar
Josephine Gowing
 
Posts: 3545
Joined: Fri Jun 30, 2006 12:41 pm

Post » Fri Sep 03, 2010 4:15 pm

Pinpointed the IsKeyPressed2 issue a little further:

The first text does not print. The second does.
And, after this, any other "IsKeyPressed2 0" returns true on that frame, including from a different mod.
Crazy!!

if  IsKeyPressed2 0    Print "IsKeyPressed2  TRIGGERED  - Before " endifdisablecontrol 	6 	;	Block 6if  IsKeyPressed2 0    Print "IsKeyPressed2  TRIGGERED  - After " Endif


Does not happen in v19b
User avatar
sophie
 
Posts: 3482
Joined: Fri Apr 20, 2007 7:31 pm

Post » Sat Sep 04, 2010 3:12 am

There is nothing currently to determine who's attacking an actor except for actively. GetCombatTarget returns the Current Active target, the one the actor is actually hitting.



Yes there is:

scn Example

array_var TargetList
array_var ActorsAttackingMe
ref Actor
ref Enemy
short Index1
short Index2

begin *AnyBlock*
set Actor to Getself ;Or something else, just an example
let TargetList := Actor.GetTargets
let ActorsAttackingMe := ar_Construct Array
set Index1 to 0
set Index2 to 0
While (TargetList[index1])
let Enemy := TargetList[Index1]
if Enemy.GetCombatTarget == Actor
let ActorsAttackingMe[Index2] := Enemy
let index2 += 1
endif
let index1 += 1
Loop
let TargetList := ar_Null

;Array ActorsAttackingMe is now filled with all the actors currently attacking/hitting Actor

end
User avatar
Dominic Vaughan
 
Posts: 3531
Joined: Mon May 14, 2007 1:47 pm

Post » Sat Sep 04, 2010 4:11 am

Does GetNthAEData return an actor value when appropriate? It's specified to return a ref, but I can't find anything else that would.

Alternately/additionally, were the various GetTotalAE's updated with built-in IsNthAEApplied?

Edit: Docs indicate GetNthAEMagicItemIndex as a shortening of GetNthActiveEffectMagicItemIndex, but it doesn't compile.
User avatar
Hairul Hafis
 
Posts: 3516
Joined: Mon Oct 29, 2007 12:22 am

Post » Fri Sep 03, 2010 6:44 pm

Umm, you can create your own values and not interfere with any other settings in the INI file... If I'm not mistaken that saves the values in .ini. Not the master ini file.
The INI functions look up the game's master INI setting collection. IIRC, they are console commands to being with. INI writing/reading functions are only available through Pluggy at the moment.
User avatar
Melanie Steinberg
 
Posts: 3365
Joined: Fri Apr 20, 2007 11:25 pm

Post » Fri Sep 03, 2010 11:18 pm

if Enemy.GetCombatTarget == Actor

Again, you're missing the point! GetCombatTarget returns the ACTIVE target, not ALL of them. 5 actors attacking "Enemy" will not produce all 5 in Enemy.GetCombatTarget, only the CURRENT target it's attacking. That script is unusable, as you cannot see the Next enemy in their enemy list thats attacking them TOO. And to avoid any further on this, pm me if you want to discuss this further. As it stands, the in-game code/OBSE currently does not offer a means of seeing what enemies an actor is attacking (because there can be more than one), also GetCombatTarget doesn't work for Player.

The INI functions look up the game's master INI setting collection. IIRC, they are console commands to being with. INI writing/reading functions are only available through Pluggy at the moment.

Yeah, I couldn't remember if it was Pluggy or not, but since I don't need to store static data outside of the game, I haven't delved into it, besides I found Pluggy to be at best... unstable. Maybe boost the INI code to offer custom mod segments as well as values.

GuruSR.
User avatar
alicia hillier
 
Posts: 3387
Joined: Tue Feb 06, 2007 2:57 am

Post » Sat Sep 04, 2010 12:44 am

GuruSR, I believe you're looking for http://cs.elderscrolls.com/constwiki/index.php/GetTargets.
User avatar
Kieren Thomson
 
Posts: 3454
Joined: Sat Jul 21, 2007 3:28 am

Post » Fri Sep 03, 2010 2:08 pm

I'm having a problem with an OnHit event handler. It is set so that it deals even more damage to the target in each hit, but apparently the damage from the hit and the damage from the handler seem to play too together to catch an assassination if it were to occur through the handler's extra damage.

The handler's basic mechanism is this:

Spoiler
ref attackerref targetfloat dmgBegin Function {target, attacker};(calculates the dmg...)If target.GetAV Health > dmg	target.ModAV2 Health dmgelse	target.Kill attackerEndIf...

If target's health is lower than dmg + damage dealt on hit, yet higher than damage dealt on hit alone, target dies as per ModAV2 Health instead as per kill. I could try to insert the damage done by the attacker's hit in the 'GetAV health > dmg' part, but frankly I would prefer to avoid the hassle of having to precisely calculate the current damage done by attacker.

Is there any detailed info about handlers? Do they need to be reinitialized in every game session? The documentation page doesn't give much info, and they look like magic to me, like a single object script being applied to all and anything the scripter wants...
User avatar
Lalla Vu
 
Posts: 3411
Joined: Wed Jul 19, 2006 9:40 am

Post » Sat Sep 04, 2010 12:20 am

Migck, is that directly from your script? If so, the problem is that you're treating dmg as positive for the health comparison. Assuming dmg is a negative number (as implied by the ModAV2 line), your condition is always true.
User avatar
FirDaus LOVe farhana
 
Posts: 3369
Joined: Thu Sep 13, 2007 3:42 am

Post » Sat Sep 04, 2010 5:49 am

if(IsModLoaded "za_bankmod.esp")		Let r := GetFormFromMod "za_bankmod.esp" "00C1B7"		if(r)			PrintD "Found it: " +$r			if(r.GetOwner == playerref)				PrintD ">>>>>>>>> Player has it"			else				PrintD ">>>>>>>>> Chest is not player owned"			endif		endif	endif


Why don't I see any output after the Found it line, that correctly displays the name? (0019b)
User avatar
Cccurly
 
Posts: 3381
Joined: Mon Apr 09, 2007 8:18 pm

Post » Sat Sep 04, 2010 6:04 am

Because r is a base object, not actually a reference. Use "GetOwner r", not "r.GetOwner". The script is crashing at runtime because of this.

I'm not sure a base object can even have an owner, but that's a separate issue.
User avatar
Tracey Duncan
 
Posts: 3299
Joined: Wed Apr 18, 2007 9:32 am

Post » Fri Sep 03, 2010 4:13 pm

Migck, is that directly from your script? If so, the problem is that you're treating dmg as positive for the health comparison. Assuming dmg is a negative number (as implied by the ModAV2 line), your condition is always true.

I have to stop scripting at 5:00 AM... Or to start liking coffee...
User avatar
Leilene Nessel
 
Posts: 3428
Joined: Sun Apr 15, 2007 2:11 am

Post » Fri Sep 03, 2010 9:05 pm

I have to stop scripting at 5:00 AM... Or to start liking coffee...

Hey, I only identified it because I've done it half a dozen times.

And I call your scripting at 5:00 AM, and raise you scripting at 5:00 AM while liking alcohol. :P
User avatar
Charles Weber
 
Posts: 3447
Joined: Wed Aug 08, 2007 5:14 pm

Post » Fri Sep 03, 2010 7:08 pm

Because r is a base object, not actually a reference. Use "GetOwner r", not "r.GetOwner". The script is crashing at runtime because of this.

I'm not sure a base object can even have an owner, but that's a separate issue.

Thanks. I had the correct GetOwner call but was calling GetFormFromMod with a base object, when I needed a ref.
User avatar
CSar L
 
Posts: 3404
Joined: Fri Nov 09, 2007 9:36 pm

Post » Sat Sep 04, 2010 2:33 am

GuruSR, I believe you're looking for http://cs.elderscrolls.com/constwiki/index.php/GetTargets.

Please read the OBSE documentation on GetTargets, as GetTargets returns a list of "possible" targets to fight, not ones currently fighting you or any actor.

if(IsModLoaded "za_bankmod.esp")		Let r := GetFormFromMod "za_bankmod.esp" "00C1B7"		if(r)			PrintD "Found it: " +$r			if(r.GetOwner == playerref)				PrintD ">>>>>>>>> Player has it"			else				PrintD ">>>>>>>>> Chest is not player owned"			endif		endif	endif


Why don't I see any output after the Found it line, that correctly displays the name? (0019b)

I do, r.GetOwner will script crash if R isn't loaded. Just because it's referenced in memory as an object, doesn't mean it's loaded. Referencing a base object or reference to anything that has yet to be loaded will halt a script. Also, for player testing just use Player in this instance. If you know the object type, using GetObjectType will save you a headache, so after the if®, do a second if level testing if(r.GetObjectType == type). I use GetObjectType a lot when dealing with ref's of actors between save game loads, as after a load, those ref's are usually wrong if they're in another cell (as in not loaded, dead) and trying to access them script halts, but GetObjectType won't halt the script on bad refs (thankfully).

Because r is a base object, not actually a reference. Use "GetOwner r", not "r.GetOwner". The script is crashing at runtime because of this.

I'm not sure a base object can even have an owner, but that's a separate issue.

Actually, base actors can have owners. Most likely one of two things, the object isn't loaded and/or the playerref he's using didn't load (was in another cell after a game load). He should printD all over the place showing all the variables he's using so he can track where it stops.

GuruSR.
User avatar
Enny Labinjo
 
Posts: 3480
Joined: Tue Aug 01, 2006 3:04 pm

Post » Fri Sep 03, 2010 5:46 pm

Actually, base actors can have owners. Most likely one of two things, the object isn't loaded and/or the playerref he's using didn't load (was in another cell after a game load). He should printD all over the place showing all the variables he's using so he can track where it stops.
Base objects can't have owners - Ownership data is stored as extra data on references.
User avatar
Madeleine Rose Walsh
 
Posts: 3425
Joined: Wed Oct 04, 2006 2:07 am

Post » Sat Sep 04, 2010 1:38 am

Again, you're missing the point! GetCombatTarget returns the ACTIVE target, not ALL of them. 5 actors attacking "Enemy" will not produce all 5 in Enemy.GetCombatTarget, only the CURRENT target it's attacking. That script is unusable, as you cannot see the Next enemy in their enemy list thats attacking them TOO. And to avoid any further on this, pm me if you want to discuss this further. As it stands, the in-game code/OBSE currently does not offer a means of seeing what enemies an actor is attacking (because there can be more than one), also GetCombatTarget doesn't work for Player.


Read the script again. It's a while loop. It checks all the enemies in the vicinity of Actor with the GetTargets array, and then filters out those who are currently attacking Actor. I first use the function GetTargets on Actor, which returns the array of all enemies on Actor's target list. From that list, I filtered those who are currently attacking Actor, and voila, you have all the actors in the area currently attacking Actor. Which is what you wanted:

GetTargets returns a list of "possible" targets to fight, not ones currently fighting you or any actor


I'll stop this now, since if you still don't understand the script, I don't know what I could say to make you realize that what you want to achieve, is perfectly possible by just iterating over the Target List and then filtering those with your desired conditions.
User avatar
OnlyDumazzapplyhere
 
Posts: 3445
Joined: Wed Jan 24, 2007 12:43 am

Post » Sat Sep 04, 2010 12:37 am

no0b question of 2010 :
OnHit				target:ref attacker:ref				OnHitWith			target:ref weapon:form
So how this form type differs from the ref type ?

and a happy new year :celebration: :celebrate:
User avatar
xxLindsAffec
 
Posts: 3604
Joined: Sun Jan 14, 2007 10:39 pm

Post » Sat Sep 04, 2010 6:51 am

no0b question of 2010 :
OnHit				target:ref attacker:ref				OnHitWith			target:ref weapon:form
So how this form type differs from the ref type ?
It's probably a base object then.

and a happy new year :celebration: :celebrate:
A few hours earlier but yea, happy new year. :)
User avatar
TOYA toys
 
Posts: 3455
Joined: Sat Jan 13, 2007 4:22 am

Post » Fri Sep 03, 2010 6:52 pm

I don't suppose there's any way to detect which button has been clicked in a MessageBox created by another mod?
User avatar
Soraya Davy
 
Posts: 3377
Joined: Sat Aug 05, 2006 10:53 pm

Post » Fri Sep 03, 2010 9:26 pm

Question about the compiling override and plugin functions. What happens when a non-supported plugin function is used in an override block and an expression is used as an argument? A simple error I presume (in the sense that the modder is informed)?

I don't suppose there's any way to detect which button has been clicked in a MessageBox created by another mod?
Not right now but it should be very doable to get a version of GetButtonPressed that doesn't check for a matching script.
User avatar
Trevor Bostwick
 
Posts: 3393
Joined: Tue Sep 25, 2007 10:51 am


PreviousNext

Return to IV - Oblivion