Jump to content

foamyesque

Members
  • Posts

    835
  • Joined

  • Last visited

Posts posted by foamyesque

  1. Deleting records out of *.esps is bad practice in general and will lead to odd behaviour, so you shouldn't do it.

     

    That said: To actually full-up delete something, you have to remove them from the original .esps in order to see things go away. What you've done is make a copy of one of the esps with the references gone, but because the original esp is still adding them, they're still there. As far as that last esp is concerned the records you deleted out of it simply don't exist and so it never tries to modify them at all, just as it wouldn't try to modify anything that was never edited in the first place.

     

    (Which makes sense, or else the entire Skyrim world would vanish whenever someone made a mod adding a piece of armour somewhere.)

     

    If you want to revert things to vanilla, or make them go away in game, without modifying the esps that originally place them, what you want to do is edit them in your override patch, not delete. If it's new material, you can usually simply flag it as 'starts disabled'. If it's something whose enable state isn't always-on by default (e.g., a guard in a hold that changes allegiances or something), it is a bit trickier and will need to be worked out case-by-case. Another possibility for statics is to just shift them down a few hundred points on the vertical axis, which will generally stuff them safely underground, but the disabled flag's simpler and cleaner.

     

    If it's modifications to vanilla you want to revert, you'll need to copy over the original vanilla fields to your override esp for that record.

  2. First question: Does the package itself ever fire? Packages stack by order of quest priority, for example, so even if the conditions of your package are met, if another package higher in the stack also has its conditions met, yours won't be chosen. And follower AI packages are quest-driven, so they could very easily be overriding.

  3.  

    So I finally figured it out! Thanks a lot for the help dylbill.

     

    Here's a complete solution on how to check if an item was stolen during bartering/adding to a container:

    1. Prepare a custom cell (no owner npc/faction) with a helper container inside it.
    2. Create a quest with a ReferenceAlias that references the merchant's/fence's trade chest.
    3. Add a script to the ReferenceAlias

       

       

      Actor Property PlayerRef Auto
      MiscObject Property Gold001 Auto
      ObjectReference Property FenceChestRef Auto
      
      Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
      
          if akSourceContainer == PlayerRef && akBaseItem != Gold001 as Form                        ;; ensure that it was the player that added the item(s) and the item is not gold
              Debug.Trace("LevelingFenceScript: Item " + aiItemCount + "x " + akBaseItem)
              ObjectReference ref = GetReference()
              ref.RemoveItem(akBaseItem, 1, true, FenceChestRef)                                    ;; move the item to a helper container in a custom neutral cell
              ObjectReference item = FenceChestRef.DropObject(akBaseItem, 1)                        ;; drop the item in the world so we can check if it was stolen
          
              if item.IsOffLimits()                                                                 ;; check if the item was stolen
                  Debug.Trace(item.GetDisplayName() + " was stolen")
                  FO_TG_StolenTotal.Mod(aiItemCount * akBaseItem.GetGoldValue())                    ;; add to the total value of stolen items sold, TODO: implement a custom function to calc enchanted items value
                  Debug.Trace("Total value of stolen items sold: " + FO_TG_StolenTotal.GetValue())
              endIf
            
              ref.AddItem(item)                                                                     ;; add the item back
          endIf
      
      EndEvent
      

       

       

    4. Auto-Fill all properties and pick the reference for the helper container in the custom cell.

     

     

    How reliable is this if there is a duplicate item already in the container?

  4. So I have a script which basically loops activate calls on nearby alchemy plants. Problem is all the plants are activated and disappear as expected however only a single reagent is added to the players inventory. Anyone know the cause?

     

    For questions like this it would be helpful to see the actual script. Could be something that changes from the first call and the looped calls, e.g. the player stops being set as the activator.

  5. Then I think you might be stuck. I think you're going to need to edit more than just your projectiles to get this to work, since the Dawnguard bolts have the same issue. I might do some poking about and see if I can kludge up an answer via the approach I described for the unlock setup, but I'm not certain if it can be easily extended to arbitrary NPCs. I might be able to use OnEquipped to maintain a registry of who is of interest, I guess.

  6.  

    @ Shadohz
    Thanks, but your proposal is not feasible, even if you lower the 'Bolt's' damage the issue remains, the issue is the player's output damage that is reflected in his upgraded crossbow and armor's enchantments.
    @ foamyesque
    Yes, the Dawnguard exploding bolts have the same issue.
    * I still have a couple of things to experiment with, but whenever i've the time and i'm in the mood for it...
    After years of working in this project, i currently am in a state that i can't even look at the CK's desktop icon, i'm kind of fed up with it...
    Thank you both very much for your interests.

     

    Well, that's a bit annoying. Not super unexpected, though. One of the things about the game engine is that magic effects can only apply to actors. I guess dead ones don't count, and the actual physical projectile damage hits first.

     

    @Shadohz might be on to something with the damage reduction idea, though. Perks can null damage out. Whether or not you can be selective enough to completely disregard the damage if and only if the strike is coming from your crossbow bolts I don't know; I'd have to dig into the conditions and do some testing. Also not sure if how it would interact with any possible enchantments on the firing weapon, but if those enchantments are processing I suspect your bolts will be as well. Of course, if you do this, then the bolt doesn't do physical damage any more, which is a bit janky.

     

    Another possibility, which I used to hack together an Unlock spell, is to cheat a bit. Put the player in a quest alias. If they have your bolts equipped, listen for the drawing animation (or in my Unlock spell's case, the casting one). When it happens, run another quest to stuff potential targets into quest aliases that listen for an on-hit event. If the on-hit event happens, trigger the explosions and such as you do in the magic effect.

     

    If you can't listen for the drawing animation I *know* you can listen for the firing one, but if so there's the possibility that the bolt will strike someone before the aliases are filled, which will break the effect. Drawing gives the scripts more time to work with.

  7. Capture the current HP of the initial target then limit the projectile's damage to not exceed that value. It's a cheaty workaround but the player won't notice because the secondary explosive will finish the kill. Worth a shot at least.

    I'm not aware of a good way to do that dynamically.

     

    However, I wonder how the Dawnguard exploding bolts are done, and if they have the same issue. If not, you could perhaps borrow from that implementation.

  8. Yes, you should be able to. In fact, I'm not sure you need to alter the mannequin script at all (though you may need to). I'd start by giving them a new SitAt AI package -- there's a few ways to do this, but the simplest would be to just place a conventional mannequin somewhere and then put it in a quest alias -- and seeing if that works. The other bits of setting up a mannequin -- the triggerbox for activation, for example -- would need to be designed around the chair as well, but that's quite possible.

     

    I think what this *should* result in the mannequin being placed in the chair by the AI package, and then its script disabling its AI, freezing it in position.

  9.  

    @ foamyesque
    I didn't know that GOQ was tied to the frame rate, well... live one more day to learn one more thing...

     

     

    I actually looked it up! GOQ is a non-delayed native function and therefore the fastest possible kind in the game short of direct operations like addition and whatnot. List of them here: https://www.creationkit.com/index.php?title=Category:Non-delayed_Native_Function

     

    So there's no real reason to avoid using it. It's still good practice IMO to stuff it into a variable if you're going to be using it multiple times, to save your fingers if nothing else :)

  10. There is actually a performance difference. However, in most cases, it's unlikely to be dramatic.

     

    Properties get baked into saves, but many of the Papyrus functions (and GOQ is one, I believe) are tied to the frame rate of the game. So, for a given thread of the script engine, frame-linked function calls will always take at least one frame to return their result (multiple threads can process at the same time). This means that for stuff where you need to do a *lot* of things, in sequence, in a very short time -- inventory manipulation, for example -- you want to cut them to the minimum possible.

     

    However, a single call to GOQ will only take 1 frame. You can then store that in a variable on initialization of your alias, or whatever. if you need to access it repeatedly, and the performance impact is minimal.

  11. My approach is to have a dummy effect, as you do, that tracks the cooldown. The other piece is having a second spell, with a magic effect that has a script that will cast the first spell whenever the effect is triggered. Then you put whatever conditions you want on that magic effect at the spell level. I used this, for example, to simulate the once-a-day restriction on power usage when I was making a mod allowing NPCs to use the same racial powers as the player.

  12. You can use control F to change items. Unclick checkbox for same type since you want to replace a static with a container. It gives you 3 options selected item only, all items of that type in a cell or all items of that type everywhere. I've used both the single item and all cell options and they both work. Never tried the everywhere option.

     

    I have used the everywhere option, but not for something as common as a static barrel. It works but I don't know if I'd want to stress-test the CK with that many things at once :v

  13. I don't believe your end goal is doable without SKSE -- setting things on an ActorBase for the most part requires it, and, particularly, that is true of combat styles.

     

    However, there are some things you can do without that portion. It is possible to 'lock' equipment so that it is never unequipped; this does not require SKSE, but it will also stop it from ever changing, even if other, better items are added. Some additional scripting could be done to listen for gear being added to, or removed from, their inventory, upon which you might be able to update what is equipped or not. This would unfortunately mean that they would also always have their weapon(s) equipped, which could be a problem.

     

    Checking a full inventory without SKSE is possible but very much not recommended, because it is both prone to error, visible to the user if done on an NPC/the player, and very slow. Since you can't access it directly the only way I know of is to call a RemoveAll() to another container, catch all the OnItemRemoved() events (or, have a separate script on the destination container listening for OnItemAdded() events) to build a list, and then call RemoveAll() on that container to bring them all back. With actors this will result in them being naked while the thing runs, and in all cases (especially on e.g. the player) is vulnerable to stack dumping and thus giving inaccurate results, even if the Papyrus code is exactly correct.

     

    I would strongly recommend, given your desired goal, that you consider incorporating SKSE's tools here.

  14.  

     

    Keep in mind that update events do not run when the game is paused and many menus pause the game including the sleep / wait menu. So it is possible that should the update have triggered while sleeping or waiting the event will run later than intended after the menu closes.

     

    The way around this is to track the gametime and use that to adjust when the next event is registered for. So it fires for the first time, notes the current gametime, and registers for an update in seven days; when that update fires, it checks the current gametime, and then if there's been any delay, removes that much from the time period for the next registration.

     

    I personally would avoid using a script randomization loop for amounts. There's a built in tool for this in Leveled Lists; use those instead. They offer significantly more control.

     

    How do I randomize leveled lists?

     

     

    Game does it for you if you have the leveled list set up for it (i.e you do not have Use All ticked). It will randomly select 1 thing amongst all the items in the list (all of which can have independently set quantities, and which can include duplicates) at or below the player's level (there are some corner cases where it uses a different actor's level instead but they don't apply here). You can nest leveled lists inside leveled lists, as well. Between these behaviours you can basically make a leveled list generate pretty much any kind of inventory generation behaviour you want. And giving someone a random selection of items is the entire reason they were made in the first place; it drives nearly every chest and NPC inventory in the game.

     

     

     

    You mean doing something like this?

     

     

    You can use a LeveledItem object in the AddItem command directly and it will do everything for you, so there's no need to walk through the list and independently randomize the quantities.

  15. Keep in mind that update events do not run when the game is paused and many menus pause the game including the sleep / wait menu. So it is possible that should the update have triggered while sleeping or waiting the event will run later than intended after the menu closes.

     

    The way around this is to track the gametime and use that to adjust when the next event is registered for. So it fires for the first time, notes the current gametime, and registers for an update in seven days; when that update fires, it checks the current gametime, and then if there's been any delay, removes that much from the time period for the next registration.

     

    I personally would avoid using a script randomization loop for amounts. There's a built in tool for this in Leveled Lists; use those instead. They offer significantly more control.

  16. Update: After digging around a bit, I noticed the author wasn't using perks for every single ability they were including - so it seems like for some effects (i.e. improving the armor rating of heavy armor) you need to use perks and for some other effects you can just use Abilities and magic effects. Is this right?

     

    Largely. There are a number of things that perks (and perks alone) can do, and a fair number of things that magic effects can do that perks cannot. Particularly, perks cannot be dynamically added via script or any other means to any actor other than the player.

     

  17. There's only two ways for a script to be started: Through an ingame-generated event of whatever sort, or through an external function call from some other, already started, script. Ultimately that means sooner or later every script is started by an engine event of some sort.

     

    Generally the pattern I use for initializing a script is to define as many things as I can in the property and variable declarations. The OnInit() block handles things like declaring arrays, or error-checking the property settings. Any more calculation intensive material -- sorting an array, formlist manipulation, other frame-linked function calls, etc -- I offload to an OnUpdate event via a short RegisterForSingleUpdate() call at the end of the OnInit() block. The OnUpdate event is split into a 'run the first time' and 'run every other time' if necessary, by states. That way I can precisely control when the rest of the script 'turns on' and make sure it only does so once all the data is of the kind and type it expects.

×
×
  • Create New...