Jump to content

Scripting Questions


AxlDave

Recommended Posts

Okay cool, thanks for the clarifications. Odd, because I've used fTimer == n in FO3 & NV scripts before, and it worked fine... is it that Oblivion scripts function a little differently?

 

Also, if I "set HealthTotal to GetObjectHealth rCrusaderArmour", don't I need to specify that rCrusaderArmour is the reference for the current object? How do I do that without GetSelf?

Link to comment
Share on other sites

Actually it's simply to do with basic math rather. Reducing "fTimer" from "5" each frame by "- GetSecondsPassed", while "GetSecondsPassed" is the float amount of whole and fractional seconds passed since last script execution, it's rather unlikely for "fTimer" to ever reach "exactly 0.00", while it as well can just proceed into the negatives at any time.

Let "GetSecondsPassed" always be something close to 1 second for example (rounding to 2 fractional digits here for convenience):

 

fTimer = 5
5 - 1.13 = 3.87
3.87 - 1.08 = 2.79
2.79 - 1.20 = 1.59
1.59 - 1.12 = 0.47
0.47 - 0.98 = -0.51

And already you went below "0" without it ever reaching "exactly 0" on the way down.

It's almost "impossible" for random fractional numbers between "0.5" and "1.5" to ever reach "exactly 5" in sum.

And the delay between frames will never be the same or a value easily summing up to a whole in the end.

 

Not sure under what conditions it worked in FO3 or FNV before, but the functions used, or the values returned by them, must not be the same as Oblivion's.

You can very well implement a "frame" counter for instance, which will always be whole numbers anyways, but working by "seconds" you're bound to receive fractions, and these won't sum up to a whole 'ever'.

 

 

I'm not sure about the issue you seem to be having with "GetSelf" though, as "GetSelf" never failed on me so far.

It will return a different value when in inventory than when on the ground for example, but that's simple game mechanics,

and not using the old one still after the item was dropped or picked up, but obtaining the current one each frame as done in your script,

I fail to remember this ever failing on me in my scripts.

 

"If" GetObjectHealth fails with "rCrusaderArmor" as obtained by "GetSelf" though, it could be it'll need the return from "GetBaseObject" instead first,

to obtain the Base Object of "rCrusaderArmor" first before feeding it into the "GetObjectHealth" method's input.

Link to comment
Share on other sites

I see, that makes sense. Perhaps, with both Fallouts being more recent, they had a more accurate counter? Not sure.

 

Okay, I'm totally stumped here. I have altered my script according to several pieces of advice posted here, and have made some... confusing progress. I'll post the script and then the effects it has.

 

 

 

scn AXLCrusaderRepairScript

ref		rCrusaderArmour

float	fHealthCurrent
float	fHealthTotal
float	fHealthPercent
float	fOnePercent
float	fOnePercentIncrease

float	fTimer
int		iStage

BEGIN GameMode

	set rCrusaderArmour to GetSelf
	set fHealthCurrent to GetCurrentHealth
	set fHealthTotal to GetObjectHealth
	set fHealthPercent to ( fHealthCurrent / fHealthTotal ) * 100
	set fOnePercent to ( fHealthTotal / 100 )
	set fOnePercentIncrease to ( fHealthCurrent + fOnePercent )
	set fTimer to 0
	set iStage to 0

	if fHealthPercent == 125
		Message "Full Health"

	elseif fHealthPercent < 125
		Message "Low Health"

		if fTimer <= 0
			if iStage == 0
				Message "Timer Started"
				set fTimer to ( fTimer + GetSecondsPassed )
				set iStage to 1
			endif

		elseif fTimer >= 5
			if iStage == 1
				Message "Success"
				SetCurrentHealth fOnePercentIncrease
				set fTimer to 0
				set iStage to 0
			endif
		endif

	endif

END

 

 

 

Initially, I changed the variables to be floats and removed the GetSelf references. This made the "Settings Applied" message appear steadily for a second, then that and the "Low Health" message flash rapidly and alternately.

 

I then removed the "Settings Applied" message and had similar results whereby "Low Health" would appear for a second, then "Success" for a second, before both flash rapidly and alternately.

 

I then switched round the timer so it counted up from 0, and now I get the exact same response from "Low Health" and "Timer Started".

 

It looks like the script is running through the fHealthPercent < 125 block, but ignoring all commands except the message commands. No health is restored to the armour in any of the above scenarios.

 

What the phantasmagorical elephant is going on?

 

 

--EDIT--

 

After noticing a rather stupid mistake, I removed the set fTimer to 0 and set iStage to 0 commands from the beginning of the script, and now have a slightly better response. Still no health increase, but we're getting there.

 

So, now "Low Health" shows for a second, then "Timer Started" shows for a second, then "Low Health" shows continuously, but no "Success" message.

 

I shall continue to look for basic errors, if someone could point out any not so basic ones?

Edited by AxlDave
Link to comment
Share on other sites

i ll post a better one tommorow if i have the time

this script im posting is a mess but repairs a piece of armor as i tested

in the previous scripts i made based on the above i only got the armour to get repaired when was on the ground

The main loop is from cm partners (stripped and adjusted) but and from the other scripts i saw in repairing scripts they pretty use all the same loop whether its a magic effect or a token (i guess it must be the only way)

 

scn AXLCrusaderRepairScript

ref rCrusaderArmour

short HealthCurrent
short HealthTotal
short HealthPercent
short OnePercent
short OnePercentIncrease
short currentslot
float fTimer

BEGIN GameMode
if fTimer== 0
Message "Settings Applied"

set rCrusaderArmour to GetSelf
set HealthTotal to GetObjectHealth rCrusaderArmour
set HealthCurrent to GetCurrentHealth
set currentslot to GetEquipmentSlot
set rCrusaderArmour to player.GetEquippedObject currentslot

; set HealthTotal to rCrusaderArmour.GetObjectHealth
; set HealthTotal to GetObjectHealth rCrusaderArmour
set HealthPercent to ( HealthCurrent / HealthTotal ) * 100
set OnePercent to ( HealthTotal / 100 )
set OnePercentIncrease to ( HealthCurrent + OnePercent )
message "cur HP-%0.f base HP-%0.f per-%0.f", HealthCurrent, HealthTotal, HealthPercent;
set ftimer to 1
endif
; Main Loop
set rCrusaderArmour to player.GetEquippedObject currentslot

if ftimer == 1
if (rCrusaderArmour)
if player.GetEquippedCurrentHealth currentslot < player.GetObjectHealth rCrusaderArmour
set OnePercentIncrease to ( player.GetObjectHealth rCrusaderArmour - player.GetEquippedCurrentHealth currentslot )
player.ModEquippedCurrentHealth OnePercentIncrease currentslot

return
else

endif

endif

; "Repaired slot %f by %f" slot repair



;if HealthPercent == 125
; Message "Full Health"
;RETURN

;elseif HealthPercent < 125
;Message "Low Health"


;if fTimer > 0
; Message "Timer Started"
;set fTimer to ( fTimer - GetSecondsPassed )
;endif

; if fTimer == 0
; Message "Success"
; rCrusaderArmour.SetCurrentHealth OnePercentIncrease
;set fTimer to 5
;endif
; if HealthPercent < 95
;SetCurrentHealth OnePercentIncrease
;endif



endif

END

 

Link to comment
Share on other sites

Okay, further update - I have isolated the problem, I think. The SetCurrentHealth fOnePercentIncrease does not appear to do anything. Using my latest script (below), the only message that pops up is the "Success" one, which happens every 5 seconds as required.

 

However, still no health increase. Perhaps my maths is wrong? Or maybe I'm back to the original problem of how to reference the armour that is the subject of this script?

 

 

 

scn AXLCrusaderRepairScript

ref		rCrusaderArmour

float	fHealthCurrent
float	fHealthTotal
float	fHealthPercent
float	fOnePercent
float	fOnePercentIncrease

float	fTimer
int		iStage

BEGIN GameMode

	set rCrusaderArmour to GetSelf
	set fHealthCurrent to GetCurrentHealth
	set fHealthTotal to GetObjectHealth
	set fHealthPercent to ( fHealthCurrent / fHealthTotal ) * 100
	set fOnePercent to ( fHealthTotal / 100 )
	set fOnePercentIncrease to ( fHealthCurrent + fOnePercent )

	if fHealthPercent == 125

	elseif fHealthPercent < 125

		if fTimer > 0
			set fTimer to ( fTimer - GetSecondsPassed )

		elseif fTimer >= 5
			Message "Timer Started"

		elseif fTimer >= 4
			Message 4

		elseif fTimer >= 3
			Message 3

		elseif fTimer >= 2
			Message 2

		elseif fTimer >= 1
			Message 1

		elseif fTimer <= 0
			Message "Success"
			SetCurrentHealth fOnePercentIncrease
			set fTimer to 5
		endif

	endif

END

 

 

Edited by AxlDave
Link to comment
Share on other sites

this seem to be running and changes values when eqquiped

i forgot to change the shorts to floats again

 

scn AXLCrusaderRepairScript

ref rCrusaderArmour

short HealthCurrent
short HealthTotal
short HealthPercent
short OnePercent
short OnePercentIncrease
short currentslot

float HealthCurrent2


short phase

float fTimer

begin onequip
set phase to 1 ;;;;;;;;;dont need this
set fTimer to 6
set currentslot to GetEquipmentSlot
set rCrusaderArmour to player.GetEquippedObject currentslot
end


BEGIN GameMode

if (rCrusaderArmour)
set HealthTotal to GetObjectHealth rCrusaderArmour
set HealthCurrent to GetCurrentHealth
set healthcurrent2 to player.GetEquippedCurrentHealth currentslot ;;;;;;dont need this
set HealthPercent to ( HealthCurrent / HealthTotal ) * 100
set OnePercent to ( HealthTotal / 100 )
message "HealthTotal-%0.f HealthCurrent-%0.f HealthCurren2 -%0.f Hper-%0.f OnePercent-%0.f ", HealthTotal ,HealthCurrent ,HealthCurrent2 ,HealthPercent ,OnePercent;


if HealthPercent < 125
set ftimer to ftimer - GetSecondsPassed
if ftimer <= 0
set fTimer to 6
message "success"

player.ModEquippedCurrentHealth OnePercent currentslot
endif
return

else

endif



endif







END

 

Link to comment
Share on other sites

I was kind of hoping to not limit it to equipped stuff. The script I posted above seems to work except for the referencing bit. It must be possible to get the generic set / get current health commands to work, right? I can't see why they'd be there otherwise.

 

P.S. How do you do spoiler tags?

Edited by AxlDave
Link to comment
Share on other sites

i made a little progress about the loop - not finished yet - i think the script becomes big and may produce lag

anyway

 

scn AXLCrusaderRepairScript

ref rCrusaderArmour

float fHealthCurrent
float fHealthTotal
float fHealthPercent
float fOnePercent
float fOnePercentIncrease

float fTimer
short doonce
ref pcont
ref pinvobj
short invpos

ref base
ref iter

BEGIN GameMode

if doonce == 0


set doonce to 1
set fTimer to 6
endif
set rCrusaderArmour to GetSelf

set fHealthCurrent to GetCurrentHealth
set fHealthTotal to GetObjectHealth
set fHealthPercent to ( fHealthCurrent / fHealthTotal ) * 100
set fOnePercent to ( fHealthTotal / 100 )
set fOnePercentIncrease to ( fHealthCurrent + fOnePercent )
message "HealthTotal-%0.f HealthCurrent-%0.f Hper-%0.f OnePercent-%0.f OnePinc-%0.f", fHealthTotal ,fHealthCurrent ,fHealthPercent ,fOnePercent ,fOnePercentIncrease;


if fHealthPercent < 125

set ftimer to ftimer - GetSecondsPassed
if ftimer <= 0
set fTimer to 6
message "success"
;if iam in a container



set pcont to GetContainer
if pcont.IsContainer

set base to GetBaseObject

foreach iter <- pcont

if iter.getbaseobject == base

set pInvObj to iter

pInvObj.SetCurrentHealth fOnePercentIncrease

endif

loop
else
rCrusaderArmour.SetCurrentHealth fOnePercentIncrease
endif

else

endif

endif


END

 

Edited by kastano
Link to comment
Share on other sites

Ref-Walking in the inventory of the container the item currently is in to obtain the ref to the object the script is running on... looks like a rather bloated approach, but I won't be surprised, if it turned out to be necessary to be done that bloated way in Oblivion, either. An interesting approach it is no doubt.

 

I remember having had to use the function working on "equipped" items as well in my scripts, but I think it was again for different reasons only.

 

 

For what it's worth, using the iteration via "foreach" in the way posted above is definitely bound to run into game delays increasing with the size of your inventory, as foreach "stops" the game until the loop is completely done.

 

I for one prefer constructing loops in 'cooperation' with the game's main loop instead of delaying it by my own loops.

A GameMode script is already a 'loop' by design, but this one returns control to the game each frame and thus the game never freezes up like it does during "foreach".

 

You can setup your loop from above similarly just by means of a state variable (your "phase" perhaps even?) to control when you're inside the loop still and when not. I fail to remember the means to iterate the container via rev-walking without using "foreach" though, but I'm pretty sure there was a way to iterate this list step-by-step one step each frame as well.

 

 

And as for the "spoiler" tags, that's actually really simple. You can either use the 3rd button from left from the top button bar of the editor ("Special BBCode") to create a spoiler block, or you simply put the tags "spoiler" and "/spoiler" (just add square brackets) around your text to do it manually, like so:

 

...
[spoiler]
spoilered text
[/spoiler]
...
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...