Jump to content
  • Announcements

    • AndalayBay

      Orphan Attachments   07/31/2018

      I have been doing some housekeeping lately and I've noticed that I had a lot of orphaned attachments. Attachments get orphaned when the PM or post is deleted without removing the attachment first. Deleting a PM or post does not delete the attachment and the file or image remain on the server. I'd like to ask all members to go through their attachments and delete any attachments you don't need anymore or those that have been orphaned. Where can I get a list of my attachments? Click on your display name in the upper right corner of the forums and pick "My Attachments" from the drop-down list. How can I tell an attachment is orphaned? If the PM has been deleted, you'll see a message like this in your attachment list: Unfortunately there is no message if the post has been deleted, so please check your old posts. We do purge old birthday threads every once in a while. Also some hosted projects have been shut down, so you may have orphaned attachments on one of those locations. Thanks!
saebel

SDR and Oblivion XP Kill Rewards

Recommended Posts

Quick question.  So with the latest SDR, it passes on some Oblivion XP when there is a successful assassination SDR style.  SDR sends one kind of message to the upper left corner.  A second message for the XP granted pops up using XP's system.  The user who brought this to my attention was wondering if the two separate messages were necessary.  Is there a way for me to pass on more than just the xp amount?  Can I pass on a specific reason that pops up as well?  Thanks.

Share this post


Link to post
Share on other sites

I'm not sure I'm following you. I've grabbed the new SDR and I'll be installing when I get back to my game, so I might see this directly.

 

Are you using runScriptline with the interOpGainedXP variables? If so, then those variables have two components: one for a message and one for the actual experience points. It sounds like you're using both of those, so do you have to display a message in SDR as well?

Share this post


Link to post
Share on other sites

I'm not passing a second variable, so I must be missing something.   This is my code:

 

 

        if iOblivionXP > 0
            RunScriptLine "set ObXPMain.interOpGainedXP to %g" iOblivionXP
            if GetGS iSDRsMsgShowAssasination
                MessageEX "%n assassinated for %g XP!" rTarget iOblivionXP
            endif
            if iDebug
                PrintToConsole "SDR: %n assassinated for %g XP!" rTarget iOblivionXP
            endif
        endif

Share this post


Link to post
Share on other sites

Oh, I see. Well you don't need the if statement to show the points. In fact that might be confusing because Oblivion XP also levels the points, so the actual amount awarded will differ from the base value you're setting.

 

Oblivion XP always reports the number of points awarded, whether it's through the inter mod support or from the base system.

Share this post


Link to post
Share on other sites

Hmmm.   Well, considering the amount I am awarding is a variant off the kill formula, doesn't that already take level into account?   So is leveling ending up being applied a second time?  And, just to be sure I understand correctly, the amount of points I am sending to ObXP is not what actually gets awarded?

 

If so, is there any method for passing a reason to ObXP so that when points are awarded the person knows why?   It certainly would explain the confusion.  I've been under the impression that the points I've been sending are what are being awarded.

Share this post


Link to post
Share on other sites

I split your question into a new thread.

 

The problem with the interop variables is that they are normally used for quests. So the points being sent from the other mod would be just a base number of points and Ob XP applies the level calculations. Here's the formula:

 

 

let gainedXP := ( 1 + ObXPMain.playerLevel * ObXPSettings.multXPQuestLevel ) * ObXPSettings.globalQuestXPMult * interOpGainedXP

 

As you can see, it's set up for quests, not kill points. Kills in Oblivion XP are processed on an onDeath event handler. I'm guessing that if I created a new variable that you could use to pass along the points and I used it in the onDeath event handler, that would be too late, or that we couldn't rely on the timing.

 

You see, my thought is that I could create a new interop variable that I would test in the onDeath event handler. If that variable is set then I would use that in lieu of the gained XP. Then Oblivion XP could apply the sleeping bonus and award the points. I've added you to the Collective so that you can grab the new version of Ob XP. Here's the link. The script is OBXPfnOnDeath. Or if you prefer, I could paste it into a post here.

 

I did run with SDR last night and I thought I had found a bug, but then I realized it was my fault, I had set the sneaking multiplier to 0 and it should be set to 1, so I'll need to run more tests.

 

I would also suggest that you just display a message saying it's an assassination kill, as appropriate, and let Ob XP display the number of points. We do need to sort out our calculations though. :)

Share this post


Link to post
Share on other sites

I've been playing with SDR for a bit now and it's working quite well. I'd say we just need to figure out how to handle the kill points and we'll be all set.

 

However, Milotek has found an issue with my poison kill script. Apparently you get multiple awards if you keep hitting an enemy with poisoned shots. I think that all we need to do is to remove all remaining effects when we "kill" the creature manually. Apparently it's only an issue when the creature dies between passes and it's the scriptEffectFinish that processes the kill.

Share this post


Link to post
Share on other sites

I've been playing with SDR for a bit now and it's working quite well. I'd say we just need to figure out how to handle the kill points and we'll be all set.

 

However, Milotek has found an issue with my poison kill script. Apparently you get multiple awards if you keep hitting an enemy with poisoned shots. I think that all we need to do is to remove all remaining effects when we "kill" the creature manually. Apparently it's only an issue when the creature dies between passes and it's the scriptEffectFinish that processes the kill.

 

Hmm.   As I recall, my script was slightly different.  I think I ran into that bug and squished it already, but I could be wrong about that.  Do you want me to post the code again?

 

Also, yeah, if there was an alternate way to pass flat xp, that would be great.  It's a shame run script line can't handle anything beyond basic oblivion stuff, because then I could be passing strings/references in addition to numbers.  It would be nice if the whole thing (message + xp) was handled by ObXP, but I can't think of a good way of doing it without creating some sort of custom quest that runs every .05 to .1 seconds.  So perhaps something like this?

 

My thought is that it could be some sort of "ObXPxChange".

First you pass the index of the calling mod to ObXPxChange.iModIndex

Then you pass the flat amount of ObXp awarded to ObXPxChange.iXPawarded

Then you pass the award code.  This would have to be preset with a look up table or something.  Sent to ObXPxChange.iAwardeCode

0 = generic award

1 = assassination

2 = whatever.

3 = etc.

Then you would have the option of passing a ref if the code calls for it, sent to ObXPxChange.rOptRef

Then perhaps a final boolean number to let the system know that all the data was sent : ObXPxChange.iAward

 

So lets say I pass these bits of info using the following:

 

let iModIndex := GetModIndex "SDR.esm"
let iAwardAmoung := 50
let rTarget := rVictim
RunScriptLine "set ObXPxChange.iModIndex to %g"  iModIndex
RunScriptLine "set ObXPxChange.IXPawarded to %g" iAwardAmount
RunScriptLine "set ObXPxChange.iAwardCode to 1"
RunScriptLine "set ObXPxChange.rOptRef to %i" rTarget
RunScriptLine "set ObXPxChange.iAward to 1"

 

The quest would keep doing a sweep until it sees that iAward == 1, then it goes through and processes everything.

 

fquestdelaytime
short iModIndex
short iAwardAmount
short iAwardCode
ref rOptRef
short iAward
string_var sModName
string_var sMessage

Begin GameMode

    If fQuestDelayTime != .1
      let fQuestDelayTime := .1
    endif

    if iAward != 1
        return
    else
        Let sModName := GetNthModName iModIndex
        Let sMessage := sv_Construct "%z awarded you %g xp" sModName iAwardAmount
        ; award code would be used to determine the second part of the message:
        if iAwardCode == 1 ; assassination
            if rOptRef == 0 ; no ref passed
                let sMessage := sv_Construct "%z for assassinating a target!" sMessage
            else
                let sMessage := sv_Construct "%z for assassinating %n!" sMessage rOptRef
            endif
        elseif iAwardCode == 2 ; whatever
            stuff
        else ; award code unspecified or 0
            let sMessage := sv_Construct "%z." sMessage
        endif
        
        ; insert whatever needs to happen to pass on the xp and display the message in the ObXp fashion.
        
        ; clear out the variables so that they can be  used again
        sv_Destruct sModName sMessage
        let iAwardAmount := 0
        let iAwardCode := 0
        let iModIndex := 0
        let iAward := 0
        return
    endif

End

The above code would result in the following message:

"SDR.esm awarded you 50 xp for assassinating Goblin Berserker!"

 

This *might* open a can of worms because as people requested to use the feature, you would have to establish what the award codes are, what they do, and what messages get sent/used.  But presumably that info would be available to modders anyway.

 

Whaddaya think?

Share this post


Link to post
Share on other sites

Yes, please post your code.

 

Eeek! I don't think it needs to be that complicated. I can create a variable to handle kill points explicitly. I think all we need to do is to have SDR pass a base number of points and Ob XP will apply the levelling formula and the sleep bonus. SDR only needs to handle assassination kills, doesn't it? Ob XP handles regular kills. So SDR only needs to have a message for when the player gets an assassination kill and let Ob XP report the number of points awarded.

Share this post


Link to post
Share on other sites

Poison Magic Effect Script:

 

 

scn sdrMEPoisonReplacer

;this script was originally created by Andalay Bay and modified to sync with SDR approach

;this is a script effect that is added to any poison on the player's weapon
;it manually increases the player's kill counter if the actor it's applied to was killed by the poison
;the script will only run for the duration of the poison

ref rActor
ref rPoison
short iDebug

float fKillsCreatures
float fKillsNPCs

short iCodeDGHE
short iCodeDRHE
short iCodeFIDG
short iCodeFRDG
short iCodeSHDG

float fDamageDone
short iEffectNum
short iEffectCount

float fResistPoison
float fActorHealth
short iKillRegistered

float fScriptTimer

begin ScriptEffectStart

; get reference to the actor the poison is on (the target of the player)
    let rActor := GetSelf

; exit early in case for some weird reason the target is not an NPC or Creature
    if rActor.GetObjectType < 35 || rActor.GetObjectType > 36
        return
    endif        

; get reference to the original poison
    let rPoison := sdrQ.rPoison

; Check for debug mode
    let iDebug := GetGS iSDRsDebugPoisonFix

; get current values for creature and NPC kills
    let fKillsCreatures := GetPCMiscStat 5
    let fKillsNPCs := GetPCMiscStat 6

; establish effect codes
    let iCodeDGHE := MECodeFromChars "DGHE"
    let iCodeDRHE := MECodeFromChars "DRHE"
    let iCodeFIDG := MECodeFromChars "FIDG"
    let iCodeFRDG := MECodeFromChars "FRDG"
    let iCodeSHDG := MECodeFromChars "SHDG"

;go through all effects on the poison and calculate damage done by each effect
    let fDamageDone := 0
    let iEffectNum := 0
    let iEffectCount := GetMagicItemEffectCount rPoison
    while ( iEffectNum < iEffectCount )
;        initial damage equals spell magnitude
;         sum up the damage from the health related effects only (damage health, drain health, fire damage, frost damage, shock damage)
;         need to consider individual resistances before adding to total damage done.  Negative resistance is a weakness, so the damage
;         will be increased.
        if ( ( GetNthEffectItemCode rPoison iEffectNum ) == iCodeDGHE )
            let fDamageDone += GetNthEffectItemMagnitude rPoison iEffectNum
        elseif ( ( GetNthEffectItemCode rPoison iEffectNum ) == iCodeDRHE )
            let fDamageDone += GetNthEffectItemMagnitude rPoison iEffectNum
        elseif ( ( GetNthEffectItemCode rPoison iEffectNum ) == iCodeFIDG )
            let fDamageDone += GetNthEffectItemMagnitude rPoison iEffectNum * ( 100 - rActor.getAV ResistFire ) / 100
        elseif ( ( GetNthEffectItemCode rPoison iEffectNum ) == iCodeFRDG )
            let fDamageDone += GetNthEffectItemMagnitude rPoison iEffectNum * ( 100 - rActor.getAV ResistFrost ) / 100
        elseif ( ( GetNthEffectItemCode rPoison iEffectNum ) == iCodeSHDG )
            let fDamageDone += GetNthEffectItemMagnitude rPoison iEffectNum * ( 100 - rActor.getAV ResistShock ) / 100
        endif

        let iEffectNum += 1
    loop

; defenses against poison damage include resist poison, and resist elemental effects, calculated above weakness to poison enhances damage
    let fResistPoison := (100 - rActor.getAV ResistPoison) / 100
    let fDamageDone := fDamageDone * fResistPoison
    let fActorHealth := rActor.getAV Health

; check if damage is enough to kill the rActor - need to compare before and after misc. stats and possibly use kill command to get death to register
    if (( fDamageDone >= fActorHealth ) && ( fActorHealth > 0 ))
        rActor.kill PlayerRef
        if iDebug
            PrintToConsole "SDR: Poison killed %n!" rActor
        endif
        let iKillRegistered := 1
    endif

end

begin ScriptEffectUpdate
    let fScriptTimer := fScriptTimer + ScriptEffectElapsedSeconds
    if ( fScriptTimer >= 0.98 )
        let fScriptTimer := 0

;        go through all effects on the poison and calculate damage done by each effect
        let fDamageDone := 0
        let iEffectNum := 0
        let iEffectCount := GetMagicItemEffectCount rPoison
        while ( iEffectNum < iEffectCount )
            if ( ( GetNthEffectItemCode rPoison iEffectNum ) == iCodeDGHE )
                let fDamageDone += GetNthEffectItemMagnitude rPoison iEffectNum
            elseif ( ( GetNthEffectItemCode rPoison iEffectNum ) == iCodeDRHE )
                let fDamageDone += GetNthEffectItemMagnitude rPoison iEffectNum
            elseif ( ( GetNthEffectItemCode rPoison iEffectNum ) == iCodeFIDG )
                let fDamageDone += GetNthEffectItemMagnitude rPoison iEffectNum * ( 100 - rActor.getAV ResistFire ) / 100
            elseif ( ( GetNthEffectItemCode rPoison iEffectNum ) == iCodeFRDG )
                let fDamageDone += GetNthEffectItemMagnitude rPoison iEffectNum * ( 100 - rActor.getAV ResistFrost ) / 100
            elseif ( ( GetNthEffectItemCode rPoison iEffectNum ) == iCodeSHDG )
                let fDamageDone += GetNthEffectItemMagnitude rPoison iEffectNum * ( 100 - rActor.getAV ResistShock ) / 100
            endif
            let iEffectNum += 1
        loop

        let fResistPoison := (100 - rActor.getAV ResistPoison) / 100
        let fDamageDone := fDamageDone * fResistPoison
        let fActorHealth := rActor.getAV Health
;        check if damage is enough to kill the actor
        if (( fDamageDone >= fActorHealth ) && ( fActorHealth > 0 ))
            rActor.kill PlayerRef
            if iDebug
                PrintToConsole "SDR: Poison killed %n! (scenario 1)" rActor
            endif
            let iKillRegistered := 1
        endif
    endif
end

begin ScriptEffectFinish

    let sdrQ.rPoison := 0

; the resistances of certain creatures isn't captured properly, so they die in between the update cycles
; try to capture those cases here - return in update cycle not working.  Also need to account for critter
; dying by brute force, in which case the kill will be registered by the regular kill script.

    if iKillRegistered
        return
    endif

    if rActor.GetDead
        if rActor.IsCreature
            if ( GetPCMiscStat 5 == fKillsCreatures )
                ModPCMiscStat 5 1
                if iDebug
                    PrintToConsole "SDR: Poison killed %n! (scenario 2)" rActor
                endif
;                 check for assassination skill up directly, because OnDeath handler probably missed it
                if PlayerRef.isSneaking
                    Call sdrEHAssassinationCheck rActor PlayerRef 1
                endif
            endif
        else
            if ( GetPCMiscStat 6 == fKillsNPCs )
                ModPCMiscStat 6 1
                if iDebug
                    PrintToConsole "SDR: Poison killed %n! (scenario 3)" rActor
                endif
;                 check for assassination skill up directly, because OnDeath handler probably missed it
                if PlayerRef.isSneaking
                    Call sdrEHAssassinationCheck rActor PlayerRef 1
                endif
            endif
        endif

    endif

end

Share this post


Link to post
Share on other sites

Heh, I had the variable, I just didn't test for it being set already. :P Thanks saebel.

 

So how would you like to handle the kill points? Could you just pass along a base number of points and I'll process them in Ob XP? I'll define a kill variable.

Share this post


Link to post
Share on other sites

Well, since I'm using OB Xp's kill formula as the basis, it already includes leveling factors.  So it uses that formula as a base and then determines how much to add on top.  So technically, I'm just passing a number that should just be applied without any additional leveling.  If you want to adjust for sleeping, that would make sense.

 

Here's my chunk of code that determines the OB xp amount to send.

 

; Uses Oblivion XP system if loaded
    if IsModLoaded "Oblivion XP.esp"
;         Grabs skill up settings
        RunScriptLine "set sdrQ.fObXpBaseKillXp to ObXPSettings.multXPKillBase"
        RunScriptLine "set sdrQ.fObXpKillLevelMult to ObXPSettings.multXPKillLevel"
        RunScriptLine "set sdrQ.fObXpKillSneakMult to ObXPSettings.multXPKillSneaking"
;         Calculates XP to apply
        Let iOblivionXP := ( sdrQ.fObXpBaseKillXp / iLevelKiller ) * ( (Log10 iLevelTarget) + ( iLevelTarget * (sqrt iLevelTarget) ) ) * ( 1 + iLevelKiller * sdrQ.fObXpKillLevelMult )
        if iCloseKill
            Let fOblivionXPMult := (GetGS fSDRsObXPClose)
        else
            Let fOblivionXPMult := (GetGS fSDRsObXPRanged)
        endif
        if sdrQ.fObXpKillSneakMult > 1
            Let fOblivionXPMult /= 2
        endif
        Let iOblivionXP *= fOblivionXPMult
        if iDeathDueToPoison
            Let iOblivionXP *= (GetGS fSDRsASkUpPoisonMult)
        endif
        if iOblivionXP > 0
            RunScriptLine "set ObXPMain.interOpGainedXP to %g" iOblivionXP
            if GetGS iSDRsMsgShowAssasination
                MessageEX "%n assassinated for %g XP!" rTarget iOblivionXP
            endif
            if iDebug
                PrintToConsole "SDR: %n assassinated for %g XP!" rTarget iOblivionXP
            endif
        endif
        return
    endif

 

Presumably, since the amount is going to be altered, I should strip the amount from the messages above, yes?  Then there will be two messages: the first will be from SDR saying "blah blah assassinated!"  and then ObXP will provide a second message that just says something like "blah XP awarded".  Is that how it will work?

Share this post


Link to post
Share on other sites

The base formula has two adjustments: an amount to account for level, which you have and a factor for party size. The player gets credit for companion kills, but all kills, whether by the player or one of his companions, don't earn as many points as would be earned if the player was by himself. Do you take party size into account at all? Do you think we need to?

 

Once the base amount is calculated, then the rest factor is applied, which I can apply in Oblivion XP when I process the points being awarded from SDR.

 

Then yes, you would just let the player know whether they got an assassination kill or not and Ob XP would report the number of points awarded.

Share this post


Link to post
Share on other sites

The base formula has two adjustments: an amount to account for level, which you have and a factor for party size. The player gets credit for companion kills, but all kills, whether by the player or one of his companions, don't earn as many points as would be earned if the player was by himself. Do you take party size into account at all? Do you think we need to?

 

Once the base amount is calculated, then the rest factor is applied, which I can apply in Oblivion XP when I process the points being awarded from SDR.

 

Then yes, you would just let the player know whether they got an assassination kill or not and Ob XP would report the number of points awarded.

I decided not to incorporate party size.  Assassination is a one on one sort of thing, and my rules make it more difficult.  The player has to be the killer, and it has to be "clean", which means the target can't be alarmed or in combat or other various factors.  So if another party member is the killer, the player won't get any assassination points.  Having other companions around actually makes that more difficult to accomplish, especially at close range.  So I don't think the points should be adjusted due to companion count.  A real assassin wouldn't be going off assassinating anyone with a companion around unless they were also an assassin type, otherwise they risk being given away.

 

Side note:  Although I *want* to use alarmed as an option, unfortunately, sometimes using "GetAlarmed" causes a CTD.  I'm not entirely sure under what circumstances, so until I sort that out, I have place holders for it.

If the resting modifier has to do with the target sleeping, I'm planning on incorporating that.  I already have a setting for it for the alternate sneak skill up feature, I just forgot to apply it to the assassination part.  So in theory, you shouldn't have to do any post processing.

Share this post


Link to post
Share on other sites

So your kill rewards are strictly for an assassination? If so, then that's good - Ob XP's regular calculations will kick in at other times.

 

The sleeping bonus applies to the player. They get double the number of points while they are well rested. Skyrim uses the same mechanic, although Sir Frederik did it first. :P

Share this post


Link to post
Share on other sites

So your kill rewards are strictly for an assassination? If so, then that's good - Ob XP's regular calculations will kick in at other times.

 

The sleeping bonus applies to the player. They get double the number of points while they are well rested. Skyrim uses the same mechanic, although Sir Frederik did it first. :P

Yes.  My reward is only given when the assassination conditions are met.

 

Regarding being "rested" status:

I don't recall seeing a "rested" factor in the original Ob XP kill formulas you sent me as a reference, but I could be mistaken.  How is the rest factor applied to a kill?  Does it matter if the player makes the kill or one of the party members makes the kill?

 

My gut reaction is that it shouldn't matter how rested they are.  What's important is whether or not they meet the criteria for the clean kill.  But if rest factor is part of the basic kill formula, then in theory SDR should follow that pattern and emulate it for determining the base kill xp before determining the clean kill bonus.

 

SDR already has interactions set up with real sleep/hunger/thirst mods that impact the player's effective stealth skill when going one-on-one against a target.  So if someone has one of those three mods installed and they haven't been sleeping/eating/drinking, it will make it easier for the target to detect the player, which will make it more difficult to meet the "clean kill" criteria.  So folks who have those mods are already penalized for being tired, but they aren't being rewarded for being rested.

 

What's your take on this?  What fits into the Oblivion XP perspective?

 

C.

Share this post


Link to post
Share on other sites

The sleeping bonus applies to all points earned while the player still has points in the sleeping pool. Once all the sleeping bonus points are used up, the point rewards return to normal.

 

Alright, so I'll create two new variables:

 

 

float interOpKillXP
string_var interOpKillXPMessage

 

The interOpKillXP will be for the point award and the interOpKillXPMessage will be for an optional message. Perhaps we could use it to display the assassination message, if you like. I'm still not quite sure how this is going to work. I'm just wondering about the timing. I might have to put a check in Ob XP's onDeath handler so that it doesn't process the points as well. The interoperability variables are usually processed in Ob XP's main script.

 

Do you know if Oblivion XP's onDeath event handler would fire when there's a successful assassination? If so, then perhaps I should process the interop variables there. I don't think it does, which surprises me a bit.

 

Also, one thing I forgot to ask about earlier. I see that you're dividing Ob XP's sneak kill variable by 2 if it's greater than 1. So if a player sets it to 3, they will get a sneak bonus of 1.5. Is that what you intend? I've told players that they should set the sneak bonus to 1 if they are using SDR, which basically negates the sneak bonus.

Share this post


Link to post
Share on other sites

The sleeping bonus applies to all points earned while the player still has points in the sleeping pool. Once all the sleeping bonus points are used up, the point rewards return to normal.

 

Alright, so I'll create two new variables:

float interOpKillXP
string_var interOpKillXPMessage

The interOpKillXP will be for the point award and the interOpKillXPMessage will be for an optional message. Perhaps we could use it to display the assassination message, if you like. I'm still not quite sure how this is going to work. I'm just wondering about the timing. I might have to put a check in Ob XP's onDeath handler so that it doesn't process the points as well. The interoperability variables are usually processed in Ob XP's main script.

 

Do you know if Oblivion XP's onDeath event handler would fire when there's a successful assassination? If so, then perhaps I should process the interop variables there. I don't think it does, which surprises me a bit.

 

Also, one thing I forgot to ask about earlier. I see that you're dividing Ob XP's sneak kill variable by 2 if it's greater than 1. So if a player sets it to 3, they will get a sneak bonus of 1.5. Is that what you intend? I've told players that they should set the sneak bonus to 1 if they are using SDR, which basically negates the sneak bonus.

Re: sleeping pool points :  gotcha.  Then there is no need for me to worry about that.

 

interOpKillXP, no problem.   I've been using integers, but from what other players have told me, XPs are actually handed out in floats.  Is there a preferred decimal stop?  Like .2f?

 

I'm confused about what you mean by the on death handler.  I'm only handing out bonus points for a clean kill.  Not the kill the points.  So you would still need the on death handler to calculate the base amount.  Unless I am misunderstanding what's happening (which is quite likely).

 

re: the divider, that was just a cheap hack way of catching if someone forgot to change the default setting to 1 and left it at 2.

 

Can you send me the Ob XP formula again?  Maybe I've missed something and am awarding more points than intended.

Share this post


Link to post
Share on other sites

I guess I'm confused too. :P I thought you were doing the full kill awards. If you're just replacing the sneak bonus, then I'll want to give the interop variable a different name and definitely handle it in the onDeath handler if I can.

 

Could you tell me how to get the assassination bonus? I got it early in my game, but haven't gotten it since. I prefer to use ranged magical attacks and I suspect I'm too far away.

 

I'll need to so some testing regarding the timing then. I suspect the onDeath handler will fire first, which means that I won't be able to handle the bonus in the handler. That makes things harder.

 

In terms of the variables, the XP is definitely a float. I never round it, although I do display it as an integer. If you're doing a sneak bonus, then I'd go with a float with a couple of decimal places - it will give you finer control that way.

 

So let me know how to increase the likelihood for an assassination and I'll do some testing to see if I can process your bonus in the onDeath handler. Then we can figure out variable names and the calculations. Sound good?

Share this post


Link to post
Share on other sites

I guess I'm confused too. :P I thought you were doing the full kill awards. If you're just replacing the sneak bonus, then I'll want to give the interop variable a different name and definitely handle it in the onDeath handler if I can.

Correct, I'm just replacing the sneak bonus.  But I'm using a variant of the kill formula to determine what that bonus is based on. I found a copy of the original script/formula, and I'm making a slight tweak to the bonus multipliers.  I think they were too high.  Ranged was x1 (double base) and Close was x2 (triple base).  I'm changing them to .75 and 1.25 respectively.  So a 75% bonus for ranged and a 125% bonus for close.

 

Could you tell me how to get the assassination bonus? I got it early in my game, but haven't gotten it since. I prefer to use ranged magical attacks and I suspect I'm too far away.

Here are the conditions for a clean kill:

- target must not be in combat

- target cannot be essential

- player must be completely be unobserved/undetected by anyone (except companions/summoned followers - they are ignored)

- target cannot be alarmed (not actually working properly, but it's the concept that counts because of CTDs)

- player must either have a sneak skill below 100 or have sneak skill uncapped

 

I'll need to so some testing regarding the timing then. I suspect the onDeath handler will fire first, which means that I won't be able to handle the bonus in the handler. That makes things harder.

I don't think the OnDeath handler will necessarily work, because it will depend on which order they get processed when the save game loads.  Even though SDR.esm loads before Oblivion XP, it's possible that SDR on death handler event gets registered after Ob XP.  It all depends on the timing of the start up scripts, number of returns and fquestdelay timers.  If mine gets registered after yours, yours will kick in first and not catch what mine is doing, I'm fairly certain.

 

In terms of the variables, the XP is definitely a float. I never round it, although I do display it as an integer. If you're doing a sneak bonus, then I'd go with a float with a couple of decimal places - it will give you finer control that way.

I'll truncate the result to 2 decimal places.

 

So let me know how to increase the likelihood for an assassination and I'll do some testing to see if I can process your bonus in the onDeath handler. Then we can figure out variable names and the calculations. Sound good?

I think you will find the only sure fire way is to create a quest script that does a sweep for the passed variables, something like what I posted earlier.  I'm also fairly certain that you can't pass strings with run script line. You can only simulate hand typed console commands, which can't really handle obse command structures, I think.

 

If it's too much trouble, I can write the quest script for you, or I can just scrap the SDR system. I'm not an Oblivion XP user, I just added it because people wanted the option to get OB Xp awards for sneak kills the SDR way.

 

Oh also, I've decided that if SDR detects that the user has not disabled the sneak skill up amount by setting it to 1, SDR will not award any Ob XP. That's the safest way to do it I think, rather than the divide thingy hack I did.

Share this post


Link to post
Share on other sites

Right, I think I remember what happened now. Originally you were just going to calculate the sneak bonus, but when we couldn't figure out how to process that, I think we changed it so that you did the entire kill reward.

 

Anyway, that doesn't matter - it just occurred to me that I can process a sneak bonus being delivered from SDR. Just ignore Oblivion XP's sneak multiplier. If you are sending a sneak bonus, I'll use that instead.

 

Here's my plan:

  1. Create a new interop variable called interOpSneakKill. I'll also create a string variable called interOpSneakKillMsg to hold a message. Yes, you can pass strings.
  2. I will test to see if that variable is set in the onDeath handler function. If it is, I will do the regular kill calculations and apply your sneak kill bonus instead of Oblivion XP's.
  3. I will also test to see if that variable is set in the main quest script where interop variables are normally processed. If the variable is set, but the onDeath handler hasn't processed the kill, then I will call the onDeath handler manually.

The last part is what I forgot: I can call the handler manually. It's just a function. So all you need to do is calculate the bonus if the person is running Oblivion XP. I'll watch for the sneak kill interop variables being set and then I will process them. After I have processed them, I will set them to zero and null so they are only processed once. I suggest you do the same.

 

One last thing about the bonuses: since these are bonuses, they need to be greater than one. So when you said a 75% bonus for a sneak ranged kill, you actually mean 1.75, right? Otherwise there's no bonus for doing a sneak kill. If the player stood up so he was detected, he'd get more points. :P You can send along 0.75 or whatever your calculations need, I just need to know how to process the bonus. Currently Oblivion XP's sneak bonus is a straight multiplier, so I take the kill points and multiply them by the sneak bonus. If you are just doing the bonus, then I need to take the points, multiply them by your bonus and add that to the base number of points. That's fine, I can do that, I just need to know which way you are going to calculate the bonus.

 

So if the player is running Oblivion XP, then you just need to calculate the bonus and send it along. Oblivion XP will process it and display the message. Here's how the interop string message is processed:

 

 

        let msg := mqGetMenuGlobalStringValue "Obxp\_gained" + sv_Construct " %.2f " gainedXP + mqGetMenuGlobalStringValue "Obxp\_pts" + sv_Construct "%z" interOpGainedXPMessage

 

Yes, it's basically impossible to read. :P Oblivion XP has a strings.xml file which has been translated into several languages, so I grab the first part of the message from the strings file. At the very end, the interop string message is tacked on. So you get a message like this:

 

"Gained 250 XP.  Completed The Big Quest."

 

The string interop variable has "Completed The Big Quest" in it. It's done that way so that the player sees that they are getting the points for completing a specific quest. As you can see, the current interop variables are intended for quests, not kills.

 

The kill message looks like this:

 

 

            ; This will produce a message like: Gained 26.67 XP. Killed Timberwolf (level 4).
            let msg := mqGetMenuGlobalStringValue "Obxp\_gained" + sv_Construct " %.2f " gainedXP + mqGetMenuGlobalStringValue "Obxp\_pts" + " " + mqGetMenuGlobalStringValue "Obxp\_killed" + sv_Construct " %n (" target + mqGetMenuGlobalStringValue "Obxp\_actorLvl" + sv_Construct " %.0f)." actorLevel

 

So I suggest that you send a message like "Assassination kill" or "Successful assassination" and I will tack that on to the end of the kill message. This will let the player know that they got an assassination with the appropriate bonus.

 

Lastly, your alert code is working. I've gotten assassination kills and I've found I don't get the assassination if the PC has been alerted. My sneak icon is dull, so they haven't detected me, but they've got their weapon out and are searching. If I kill them, I just get the regular kill points. I haven't tried waiting until they stop searching and put their weapon away.

Share this post


Link to post
Share on other sites

Ahhghh. I don't know why I am having so much trouble communicating what I am doing.

 

I am NOT giving them kill points. Only a sneak kill bonus. Ob XP gives the kill xp. SDR only determines if they should get an additional bonus.

 

The bonus will NOT be applied if the Ob XP Sneak mult is anything other than 1. If it sees anything else, it will assume that the user wants to use OB Xps system instead, otherwise there will be way too many points awarded.

 

The bonus is determined by (somewhat) recreating what the kill amount would be, ignoring factors for companion counts.

That recreated formula determines the base, and then the bonus awarded is calculated off that.

 

.75 base (ranged) or 1.25 base (close). So this is on top of the kill award that Ob XP granted.

 

If I did 1.75 and 2.25, then they would get way too many points because they are already getting the kill bonus, so that would mean their grand total would end up being 2.75 and 3.25 respectively.

 

-----------------------------------

I'm pretty sure I won't need to set anything to zero on my end, since the process is only one-way and can only happen once per kill.

 

If I understand correctly, this is what should happen:

 

1. My on death handler kicks in.

2. If the player is the killer then it runs the assassination sub-routine check.

3. If the scenario clears all the requirements, an assassination bonus is calculated.

4. If Ob XP is detected and the Ob XP sneak mult is 1, then it will use SDR's calcs to hand out OB XP, passing two variables:

= the first is the ob xp amount sent to interOpSneakKill, which on your end will be transformed into "Gained 50 XP."

= the second is the message that should go with it sent to interOpSneakKillMsg, which should be something like: "Goblin Warlord assassinated! Nicely done."

 

5. On your end, you will have your on death handler check to see if those variables have any data in it, and if so process them.

6. Presumably, there will be a back up to the on death handler in case our handlers get mixed up in processing order, which will sweep for those variables on a regular basis.

7. When it finds the variables, it will apply the xp and show the combined message "Gained 50 XP. Goblin Warlord assassinated! Nicely done."

8. Then it will clear the variables back to null so they can be repopulated the next time.

 

Does that all make sense / sound right?

 

(personally, I wouldn't bother with having the on death handler check for the variables, because I think it will inevitably fail at some point, and I would just rely on a regular sweep).

 

Thoughts?

Share this post


Link to post
Share on other sites

I understand what you're saying, but I'm saying that it would be better if you just calculated the bonus. Why don't we link up on Skype? I'm pretty sure we can sort this out in a few minutes. Would you mind sending me a PM with the times that you could meet for a half hour?

Share this post


Link to post
Share on other sites

I understand what you're saying, but I'm saying that it would be better if you just calculated the bonus. Why don't we link up on Skype? I'm pretty sure we can sort this out in a few minutes. Would you mind sending me a PM with the times that you could meet for a half hour?

That IS what I'm saying. I'm ONLY calculating the bonus.

 

Sent you a PM.

Edited by saebel

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×