AxlDave Posted July 28, 2014 Author Share Posted July 28, 2014 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 More sharing options...
DrakeTheDragon Posted July 28, 2014 Share Posted July 28, 2014 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 More sharing options...
AxlDave Posted July 28, 2014 Author Share Posted July 28, 2014 (edited) 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 July 29, 2014 by AxlDave Link to comment Share on other sites More sharing options...
kastano Posted July 28, 2014 Share Posted July 28, 2014 i ll post a better one tommorow if i have the timethis script im posting is a mess but repairs a piece of armor as i testedin the previous scripts i made based on the above i only got the armour to get repaired when was on the groundThe 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 AXLCrusaderRepairScriptref rCrusaderArmourshort HealthCurrentshort HealthTotalshort HealthPercentshort OnePercentshort OnePercentIncreaseshort currentslotfloat fTimerBEGIN GameModeif fTimer== 0Message "Settings Applied"set rCrusaderArmour to GetSelfset HealthTotal to GetObjectHealth rCrusaderArmourset HealthCurrent to GetCurrentHealthset currentslot to GetEquipmentSlotset rCrusaderArmour to player.GetEquippedObject currentslot; set HealthTotal to rCrusaderArmour.GetObjectHealth; set HealthTotal to GetObjectHealth rCrusaderArmourset HealthPercent to ( HealthCurrent / HealthTotal ) * 100set 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 1endif; Main Loopset rCrusaderArmour to player.GetEquippedObject currentslotif ftimer == 1if (rCrusaderArmour)if player.GetEquippedCurrentHealth currentslot < player.GetObjectHealth rCrusaderArmourset OnePercentIncrease to ( player.GetObjectHealth rCrusaderArmour - player.GetEquippedCurrentHealth currentslot )player.ModEquippedCurrentHealth OnePercentIncrease currentslotreturnelseendifendif; "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;endifendifEND Link to comment Share on other sites More sharing options...
AxlDave Posted July 29, 2014 Author Share Posted July 29, 2014 (edited) 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 July 29, 2014 by AxlDave Link to comment Share on other sites More sharing options...
kastano Posted July 29, 2014 Share Posted July 29, 2014 this seem to be running and changes values when eqquipedi forgot to change the shorts to floats again scn AXLCrusaderRepairScriptref rCrusaderArmourshort HealthCurrentshort HealthTotalshort HealthPercentshort OnePercentshort OnePercentIncreaseshort currentslotfloat HealthCurrent2short phasefloat fTimerbegin onequipset phase to 1 ;;;;;;;;;dont need thisset fTimer to 6set currentslot to GetEquipmentSlotset rCrusaderArmour to player.GetEquippedObject currentslotendBEGIN GameModeif (rCrusaderArmour)set HealthTotal to GetObjectHealth rCrusaderArmourset HealthCurrent to GetCurrentHealthset healthcurrent2 to player.GetEquippedCurrentHealth currentslot ;;;;;;dont need thisset HealthPercent to ( HealthCurrent / HealthTotal ) * 100set 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 < 125set ftimer to ftimer - GetSecondsPassedif ftimer <= 0set fTimer to 6message "success"player.ModEquippedCurrentHealth OnePercent currentslotendifreturnelseendifendifEND Link to comment Share on other sites More sharing options...
AxlDave Posted July 29, 2014 Author Share Posted July 29, 2014 (edited) 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 July 29, 2014 by AxlDave Link to comment Share on other sites More sharing options...
kastano Posted July 30, 2014 Share Posted July 30, 2014 (edited) i made a little progress about the loop - not finished yet - i think the script becomes big and may produce laganyway scn AXLCrusaderRepairScriptref rCrusaderArmourfloat fHealthCurrentfloat fHealthTotalfloat fHealthPercentfloat fOnePercentfloat fOnePercentIncreasefloat fTimershort doonceref pcontref pinvobjshort invposref baseref iterBEGIN 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 endifelseendifendifEND Edited July 30, 2014 by kastano Link to comment Share on other sites More sharing options...
DrakeTheDragon Posted July 30, 2014 Share Posted July 30, 2014 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 More sharing options...
AxlDave Posted July 30, 2014 Author Share Posted July 30, 2014 Cool, I think I'm starting to get the hang of how the inventory stuff works. Bit of a circuitous route. One question I have is foreach iter <- pcont Did you mean ForEach Iter <= PCont ? Link to comment Share on other sites More sharing options...
Recommended Posts