Jump to content
ℹ️ Intermittent Download History issues ×

Drop item script not working


Phrosen63

Recommended Posts

Hi.

 

I have a script that when I drop a certain item it should replace that item with an activator.

The script is working fine if I drop one item, then close the inventory, wait a while, then drop another item. -But if I decide to drop more than one item at the same time the script only replaces the first item; the rest of the dummy items are being dropped as if they had no script attached at all.

 

Here is the script:

Scriptname HT_PlayerDropTrap extends ObjectReference  
{A script that will replace the dummy item with an actual trap when the player drops it.}


Activator Property HT_TrapActivator  Auto

event OnContainerChanged(ObjectReference akNewContainer, ObjectReference akOldContainer)
if (akOldContainer && !akNewContainer)
	Self.PlaceAtMe(HT_TrapActivator)
	Delete()
endif
endevent

 

The script is attached to the item.

 

Some things I want to try, but don't know how, to see if it helps:

-Making the item in the player's inventory "unique" - so that they don't stack up, so that the player can't drop stacks of dummy items.

-I based the dummy item of a gem (ruby, I believe) because if you drop 5+ rubies they don't drop in one stack of five; they drop in five different stacks - which is what I want with my dummy items. I can't really tell if it's working or not, though. Is there a way to force dropped items to not stack with each other?

-Force the player to only own one dummy item at the same time. (I don't like this, but it's better than dropping dummy items, instead of activators.)

-Fix the script so that it somehow works no matter how many dummy items I drop. (This would be the best solution of all.)

 

Thanks in advance.

Link to comment
Share on other sites

Try to bind the script to the player actor and use this event:

 

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
EndEvent

 

Then inside the Event check the item to be your item.

 

Scriptname HT_PlayerDropTrap extends ObjectReference  

Item Property MyItem Auto ; I guess the syntax here is wrong :D
Activator Property HT_TrapActivator  Auto

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
   If (akBaseItem == MyItem) ; Check the item
       ; Your item
       Self.PlaceAtMe(HT_TrapActivator)
   Else
       ; Another item
   EndIf
EndEvent

 

EDIT:

You could probably try to recalculate the number of items and re-add them to the inventory if more than one is dropped.

 

Scriptname HT_PlayerDropTrap extends ObjectReference  

Item Property MyItem Auto ; I guess the syntax here is wrong :D
Activator Property HT_TrapActivator  Auto

int ReAddItems = 0

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
   If (akBaseItem == MyItem) ; Check the item
       ; Your item
       Self.PlaceAtMe(HT_TrapActivator)
       If (aiItemCount > 1) ; Check dropped item count
           ReAddItems = aiItemCount - 1 ; Number of items to re-add
           Game.GetPlayer().AddItem(MyItem, ReAddItems, true) ; Re-add the other items 
       Endif
   Else
       ; Another item
   EndIf
EndEvent

 

Of course it would be better to have only a single item dropped ... but I don't have an idea how to do THAT.

Edited by Grasmann
Link to comment
Share on other sites

I tried making a quest, adding an alias that points to "unique character -> Player" and add the script to that alias.

When nothing happened I added a few "Debug.Notification()" to see what happens. The script doesn't even run at all.

Did I do something wrong when trying to attach the script to the player?

Link to comment
Share on other sites

I believe that you will need to change the script into one that extends ReferenceAlias instead.

 

Of course! I knew that. :P

 

Here's my new code:

 

 

Scriptname HT_PlayerDropTrap extends ReferenceAlias
{A script that will replace the dummy item with an actual trap when the player drops it.}


Activator Property HT_TrapActivator  Auto
MiscObject Property HT_MyItem Auto

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
If (akBaseItem == HT_MyItem)
	akItemReference.PlaceAtMe(HT_TrapActivator)
	akItemReference.Delete()
EndIf
endEvent

 

It works really well, except for a few things:

1. HT_TrapActivator is only one activator. (I have six different.) I used to define them in each item that the script was attached to. -Now I need to check through six different items. I want to try if it's possible to do with a loop.

2. When I drop more than five (I believe) traps at once, they group up into one item with a (5) behind the name. Then the script kicks in and removes the entire group and replaces it with a single activator. -Meaning the game "steals" the player's trap. I'm gonna try to see if I can make an item counter somehow.

 

Help appriciated.

Thanks for the help so far. =)

 

 

EDIT:

I managed to solve question number 1, I am now looping through my traps and adding the correct one. Here's the script:

 

Scriptname HT_PlayerDropTrap extends ReferenceAlias
{A script attached to the player, through a quest, that will replace the dummy item with an actual trap when the player drops it.}


Activator[] Property HT_TrapActivator  Auto
MiscObject[] Property HT_MyItem Auto

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
int loop = 0

while loop < 5
	If (akBaseItem == HT_MyItem[loop])
		akItemReference.PlaceAtMe(HT_TrapActivator[loop])
		akItemReference.Delete()
                       ; I would like to break the loop here; I don't know how..
	endIf
	loop += 1
endwhile
endEvent

 

I am thinking of using another loop combined with "aiItemCount" to see if I can solve question number two, as well.

-The best way to solve it, though, would be to prevent items from grouping up when they drop. But I don't think that's possible.

 

3. Is there a way to break a loop?

Edited by Phrosen63
Link to comment
Share on other sites

I wouldn't do that with a loop in the first place.

5 different possibilities is a manageable amount for a if statement. This eliminates the need to break the loop.

 

But apart from this, I guess, you could just use "loop = 5", since the loop only continues if "loop < 5".

In every other programing language this probably would be considered dirty coding XD lol, what I guess there's nothing else you can do.

 

Like this:

Scriptname HT_PlayerDropTrap extends ReferenceAlias
{A script attached to the player, through a quest, that will replace the dummy item with an actual trap when the player drops it.}


Activator[] Property HT_TrapActivator  Auto
MiscObject[] Property HT_MyItem Auto

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
int loop = 0

while loop < 5
	If (akBaseItem == HT_MyItem[loop])
		akItemReference.PlaceAtMe(HT_TrapActivator[loop])
		akItemReference.Delete()
                       loop = 5
	endIf
	loop += 1
endwhile
endEvent

 

EDIT:

On the other hand the loop should already break through "loop += 1", which is kind of the same as my advice.

 

EDIT2:

I would be careful with quest scripts, I don't know for sure, but from my experiences there are values saved into the save game.

I don't know which values are effected, but my advice is to test this carefully.

Edited by Grasmann
Link to comment
Share on other sites

I wouldn't do that with a loop in the first place.

5 different possibilities is a manageable amount for a if statement. This eliminates the need to break the loop.

 

Anything over two needs a loop, in my opinion. It gives a cleaner code, and easier to modify.

 

 

But apart from this, I guess, you could just use "loop = 5", since the loop only continues if "loop < 5".

In every other programing language this probably would be considered dirty coding XD lol, what I guess there's nothing else you can do.

 

I actually thought of that but, as you said, it's "dirty coding". If there's a loop function there should be a break loop function, imo.

 

EDIT:

On the other hand the loop should already break through "loop += 1", which is kind of the same as my advice.

 

"loop += 1" is what makes the loop loop.

It breaks when it finishes, of course. But if it matches on item[0] it loops through four more item checks when it doesn't have to, using up CPU power.

 

 

I modified my script further, and this is what I came up with:

 

Scriptname HT_PlayerDropTrap extends ReferenceAlias
{A script attached to the player, through a quest, that will replace the dummy item with an actual trap when the player drops it.}


Activator[] Property HT_TrapActivator  Auto
MiscObject[] Property HT_MyItem Auto

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
int loop = 0
int i = 0        ; This is my second loop

while loop < 5
	If (akBaseItem == HT_MyItem[loop])

		while i < aiItemCount
Debug.Notification("traps dropped " + aiItemCount)
			;akItemReference.PlaceAtMe(HT_TrapActivator[loop])
			akItemReference.Delete()
			i += 1
		endwhile
	endIf
	loop += 1
endwhile
endEvent

 

As you can see I made the "PlaceAtMe()" function a comment, to easier see what's going on when I test it in-game. Here's what happens:

 

-If I drop a single item, it is removed (works as intended.)

-If I drop up to four items, they are removed (works as intended.) This works because the trigger runs once per item dropped.

 

-if I drop more than five items at once they will group up (not working as intended.) When the items group up the trigger runs only once, because it thinks the group is one item.

This is where my second loop comes in. I intended to loop through the group and create a new trap for each item in the group. What actually happens with my current trigger: If I drop seven items, one is removed and six dummy items are placed on the ground.

I am guessing that if I made the "PlaceAtMe()" function not a comment it would place all the activators where the group was. The activators would then trigger each other and fly all over the place. And I would also get six dummy items lying around.

 

The whole automatic group thing really messes up my trigger. =(

Edited by Phrosen63
Link to comment
Share on other sites

"loop += 1" is what makes the loop loop.

It breaks when it finishes, of course. But if it matches on item[0] it loops through four more item checks when it doesn't have to, using up CPU power.

 

Yes, of course, but the whole event is only triggered if you drop the specific item ... I guess the cpu should be able to handle this XD.

 

EDIT:

Oh I just saw the item check is inside the loop XD nevermind. But still it's only triggered if an item is dropped.

Apart from that you are right it's much more clean to break it.

 

If I understand this whole script right you want to be able to set up traps right?

So, you probably can't avoid the engine to stack more than 5 items to a group, but what's the point in setting up 10 traps to the same location anyways?

I would try to make the script only drop 1 item everytime and re-add the other items again like I suggested earlier.

Edited by Grasmann
Link to comment
Share on other sites

  • Recently Browsing   0 members

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