Is there a way to reach buggily inaccessible items?

Module authors occasionally place interactive items on blocked placeables, e.g. a helmet on a chair, a key on a dresser etc. Players are supposed to be able to pick them up, but I’ve ran into several situations now where this seems extremely difficult or not possible at all. I’m not sure if it has to do with me using the EE instead of 1.69; I guess there’s a chance the changes to pathfinding messed this up even more or something.

Now, in the module I’m currently playing, the item in question is not just any loot but a key that I need to unlock a door that’s possibly crucial for progress (picking the lock is not possible). So my question is this:

Does anyone know a way to move these items in-game, either a bit to the side, a specified place, or directly into the inventory, if it is something you can pick up? Is there a cheat command or a script I could use for it? Or do I have open the module in the toolset, find out the tag of the item and duplicate it in-game? If possible, I’d like to avoid that because, for one, the module is HUGE, and I’d also prefer not to spoil anything for me …

Yes but the method I know of works in multiplayer and is huge ass ex*loit :smiley:

You need to find the item resref via toolset and spawn it using console or toolset again.

Or if it is about locked doors, a script that unlocks nearest door would work too.

This is probably the easiest method, done within 5 minutes (or less). If you hover with the mouse over the character portrait, you see the name of the area. So it could be located within the toolset in no time. Open the area, find the item (listed unter “items” :slight_smile: ). Get the ressource reference (lower right of the properties screen) and respawn the item in-game.

1 Like

Builders’ Note:

I find that items placed directly in terrain are increasingly unreliable with EE, especially on Android.

As a workaround, I now put the item inside a placeable that looks like the item, with the OnUsed script

object oPC = GetLastUsedBy();

ActionGiveItem(GetFirstItemInInventory(), oPC);
SetPlotFlag(OBJECT_SELF, FALSE); 
ActionDoCommand(DestroyObject(OBJECT_SELF));
2 Likes

Using proper placeables is most commonly the better method, as most items have only the lootbag as 3d model.

Which reminds me: If he sees a key lying around, how can he be sure, that it’s an item and not a placeable. Actually he should see only a lootbag if it’s an item …

Maybe he has community patch installed or DOA Base Items. Or perhaps this got added into Q and CEP2 as well?

Now that you say it, I mentioned “blocked placeables” but actually the last two cases I can think of were not even placeables, just terrain, a chair and a dresser that are fixed parts of the tileset.

I also had the suspicion that it must have gotten worse with the EE. That’s unfortunate, because it means there are potential compatibility problems with old modules. :frowning:

The module in question is “Tortured Hearts I.”. From what I can see it does not use CEP or ProjectQ, just a custom hakpak.

That’s what I feared, but I didn’t realize I could get the name of the area by hovering over the character portrait. That helps a little, thanks!

I’m using CEP2 which has a wider range of suitable placeables.

What about dm_jumptopoint? jump to the position of the table? Do not know if it would work.

You can write yourself a universal, run-from-override script which will scan all seen items within ~1.5 m of PC, copy them to your inventory and destroy the originals. This will trigger OnAcquire, so nothing should break since there will be still just one item (think of unique tags). Also no need to look up ResRefs.

3 Likes

I wrote up a sample based on this. It playtested ok, too.

void main()
{
int nN = 1;
object oTarget = GetNearestObject(OBJECT_TYPE_ITEM, OBJECT_SELF, nN);
if(oTarget==OBJECT_INVALID) return;
while(GetDistanceBetween(oTarget, OBJECT_SELF)<=1.5)
    {
    CopyItem(oTarget, OBJECT_SELF, TRUE);
    DestroyObject(oTarget, 0.1);
    nN++;
    oTarget = GetNearestObject(OBJECT_TYPE_ITEM, OBJECT_SELF, nN);
    if(oTarget==OBJECT_INVALID) return;
    }
return;
//Target outside of 1.5 radius
}

I am nervous about the destroy delay being too short, but it seems to work with the counting of nearest objects at the 0.1 setting I put in.
I tested on the EE android app, using ## to access the console commands.

2 Likes

That’s one way to do it. Although in hindsight, 1.5 could be a little short (i.e. item on a big table).

Get*ObjectInShape is also a valid function here. As a bonus, it needs less code and can only capture seen items (no grabbing through walls).

GetFirstObjectInShape(SHAPE_SPHERE, 2.0, lSelf, TRUE, OBJECT_TYPE_ITEM)

You could also call SetDestroyable on the source item just in case:

AssignCommand(oTarget, SetIsDestroyable(TRUE));
AssignCommand(oTarget, DestroyObject(OBJECT_SELF));

Alternatively one could (ab)use one of the PLAYER_TOOL feats to turn it into a grabber. First script call adds the feat to PC’s skin. Then player points to the item to grab and the script moves it to inventory. A bit more complex but gives full control to the player.

2 Likes

Thank you very much! I had solved the key issue with the dm_spawnitem command, like mmat suggested, but I just ran into the same problem again with another item, so I came here with the intention of asking for help in creating such a script - and there it was already! I tried it and it worked great. :slight_smile:

Thanks a lot to @NWShacker, too, for suggesting it (and for making improvements, although I didn’t dare implement them on my own yet), and to @Proleric for explaining how to create override scripts, in the thread of another user on the Steam forums, which I used as a reference. :+1:

1 Like

… which is imo the best solution, since you learned what during the process (hopefully …). Don’t fear the toolset, it’s your friend … :slight_smile:

Good. You needed a key, which in 99.99% of cases will simply be consumed by a door. But a problem may arise when you manually duplicate a plot item without destroying the source and when the module does something like this in dialogue (check for possession):

GetItemPossessor(GetObjectByTag("WHARRGARBL")) == GetPCSpeaker();

instead of this, which is unaffected by the number of copies:

GetIsObjectValid(GetItemPossessedBy(GetPCSpeaker(), "WHARRGARBL"));

Both are valid approaches, but the first will deadlock you when the tagged item #0 (“default”) is the one you couldn’t pick. Not really module’s fault, since we’re technically cheating here, but a +1 for a scripting solution which will enforce uniqueness.

BTW, to find a world object, I prefer to click on it via DebugMode with “Object Debug Info” button to get its tag, then type that tag in Edit → Find Instance toolset dialogue.

Nah, I’ve done that before, I was just hoping that I could avoid it. I did learn that you can check the name of the area by moving the mouse cursor over the character portrait though. I mean I’ve probably seen it before without thinking about it much, but would not have connected the dots that this can help me find the area more quickly in the toolset.

In hindsight, I wouldn’t even have needed to open the toolset though, because the resref was such that I could have guessed it. (“yetanotherkey” for an item called “Yet Another Key”). :wink:

Oh, you mean I can find out about the tag of an item in-game? What button though? Is there a specific Debug Mode UI? I only ever use the “##” method with the chat bar, because the regular way of opening the cheat console (is it “^” or something?) does not seem to work with my German keyboard…

Isn’t newly spawned item the one being retrieved by GetObjectByTag?

Yes, in game. Options → Controls → Change Key Settings → DM. Sadly it doesn’t provide ResRef, but tag is enough to look it up in the toolset via Find Instance. With the other key (“Jump To Point”) you can also jump around the area – great for saving time. And of course they only work in DebugMode.

No idea. Is it? Is it always? Is it location-invariant? In any case, it is not a good idea to have duplicates of items for which uniqueness might be assumed.

Btw, yould you be willing to upload your script to the Vault as override file, or would you be okay with me doing it (giving credit to you), in case you don’t want responsibility for maintaining the page? This would make it easier for other players running into the same problem, so they wouldn’t all have to create the file themselves, and I could point players of the module to this as a workaround.

I think the two cases I encountered in Tortured Hearts could theoretically be solved with the spawnitem command, too, but the second item, a bastard sword named The Prize, doesn’t have an individual resref, so the command just spawns a regular bastard sword +2.