Difference between revisions of "Message Spam"

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search
imported>DragoonWraith
(bylined)
imported>Wrye
(Rewrite.)
Line 1: Line 1:
{{Byline}}
__NOTOC__[[Category: Useful Code]]
 
Tes4 displays messages to the player whenever: 1) spells are added to, 2) items are added to or removed from the player. For some scripts such messages are very undesirable (e.g. for an alchemical sorters which adds/removes many items). Hence, message "spam". There are several techniques for avoiding this spam.
This section is messy and needs to be cleaned up. Below, Guido gives a quite complicated answer, but from my experience and in this topic [[Preventing_messages|Preventing messages]] there's a much simpler solution:
 
In short, just a repeat a message twice in a chunk of code. Doing this will (for some bizarre reason) block any other messages from the same (frame?) of code execution. You can use empty messages to blank messages entirely. E.g.


===Message Queue Overloading===
Simplest technique is to overload the message queue by sending the exact same message twice in a row. I.e.
<pre>;--No messages.
<pre>;--No messages.
message " "
message " "
Line 13: Line 12:
message "[You've been pickpocketed!]"</pre>
message "[You've been pickpocketed!]"</pre>


----
There's no obvious reason why this does or should work, but it does. :shrug: The message that is sent (including a blank message) will still display for the usual time, but messages that would ordinarily appear after it seem to be discarded -- i.e. they never enter the queue.
 
 
AVOIDING MESSAGE SPAM WITH INVENTORY OBJECTS by Guidobot
 
 
If like me, you think it is a pain seeing messages like "xxx Added" or "xxx Removed" then check this out.
 
Here's the basic idea for adding a single item:
 
set itemRef to PlaceAtMe MyModdedItemType 1 0 0
itemRef.Activate player
 
Notes:
 
1) This method should only be used to add non-persistant objects.
 
2) The issue about requiring separate calls to retain scripts on your objects is particularly pertinent here!
 
Here's a more specific version that allows N standard items to be added to your inventory (without message spam) using an in-game function script:
 
scn MyAddItemScript
; item type/number
short numItems
short itemType
; private
short runAdd
ref itemRef
Begin OnActivate
if numItems > 0
  set runAdd to 1
endif
End
Begin GameMode
if runAdd == 0
  Return
endif
if itemType == 0
  set itemRef to player.PlaceAtMe Gold001 1 0 0
elseif itemType == 1
  set itemRef to player.PlaceAtMe Lockpick 1 0 0
elseif itemType == 2
  set itemRef to player.PlaceAtMe RepairHammer 1 0 0
elseif itemType == 3
  set itemRef to player.PlaceAtMe Torch02 1 0 0
else
  set itemRef to 0
endif
if itemRef
  itemRef.Activate player
endif
set numItems to (numItems)-1
set runAdd to numItems
End
 
Then to use:
 
; some script - example
set MyAddItemFunc.numItems to 1+0.1*GetRandomPercent; 1-10 for number
set MyAddItemFunc.itemType to 0.04*GetRandomPercent; 0-3  for type
MyAddItemFunc.Activate player 1
 
Note: Because the actual adding of multiple objects happens in GameMode, nothing will happen until this current script ends. You could easily make it add one of these in the activate block and then N-1 others, or add more than one at a time in your GameMode, etc. Additionally, the GameMode block will only fire every ~30 seconds unless the IGF item is in the same cell as the player. This is just a quick example and as with all the code here you should experiment for yourself to see what works best for your needs.
 
-----------------------
 
To drop items from your inventory without message spam, you can use the Drop method since this does not create message spam as the RemoveItem method does. Note that the Drop method also does not fire the OnDrop method.
 
To remove an item that is in your inventory you will need your own copy of the object in-game, or more likely your own scripted object. This is best done with a global variable in case you have multiple copies. In this case the global variable is in the script attached to MyQuest and the item concerned is MyItem.


Begin GameMode
'''Con:''' The downside of this approach is that it may block more messages than you want to block. It basically nukes the queue for several frames -- any message sent by any script or action during that period will be lost.
...
if MyQuest.RemoveMyItem > 0 && player.GetItemCount MyItem > 0
  set MyQuest.RemoveMyItem to (MyQuest.RemoveMyItem)-1
  RemoveMe
endif
...
End


This code will not do anything for an object (MyItem) not on a player. Since it may leave the MyQuest.RemoveMyItem set if not called appropriately you should make the object be removed silently thus:
===OBSE Commands===
As of version 0.15, [[:Category:Oblivion Script Extender|OBSE]] has commands for adding/removing objects that do not generate spam.


set MyQuest.RemoveMyItem to player.GetItemCount MyItem
See: [[AddItemNS]], [[RemoveItemNS]]


More general notes as FYI:
===Temp Container===
When adding items to the player, spam can be avoided by first adding the item to a container, and then removing the contents from the container to the player. This works because unlike addItem, [[RemoveAllItems]] is silent.
<pre>
tempContainerRef.addItem deathDagger 1
tempContainerRef.removeAllItems player 1</pre>


1) The particular objects used in the MyAddItemScript here are special and cannot be copied to objects that have the same game-play properties. They may be scripted but this is a very bad idea because of MOD conflicts and other possible issues. However, with some extra you can save a list of the object IDs (as an array or link-list) and call RemoveMe on the saved reference IDs.
If you're using [[Glossary#C|Cobl]], you can use '''cobGenXFerRef''' for the temporary container -- it's defined for just this sort of use.


2) True stacks of items, e.g. when created as a bunch with a single PlaceAtMe or AddItem call, can only be removed using RemoveItem since the base object script is not transferred. (Drop also works if you dont mind them at your feet.)
===Item Activate===
When adding items whose "activate" action results in being added to inventory (e.g. armor, but not books), you can use activate in a script.


3) I'm still working on trying to find a way to avoid EquipItem spam for stacked objects. Individually created items will retain their unique script variables, including their own reference. Hence, you can remove a specific item from an inventory stack. Unfortunately this can mess with what OB thinks is the currently equipped item if an item of a stack is equipped, whether the actual equipped instance is the one removed or not. OBSE may have methods that can help out here.
<pre>someItemRef.activate player</pre>


[[Category: Useful Code]]
'''Pro/Con:''' Requires that you have a ref for the item. On the plus side,this means that if you want the player to pick up a specific pre-existing, placed item, you can do that.

Revision as of 18:12, 31 May 2008

Tes4 displays messages to the player whenever: 1) spells are added to, 2) items are added to or removed from the player. For some scripts such messages are very undesirable (e.g. for an alchemical sorters which adds/removes many items). Hence, message "spam". There are several techniques for avoiding this spam.

Message Queue Overloading

Simplest technique is to overload the message queue by sending the exact same message twice in a row. I.e.

;--No messages.
message " "
message " "

;--OR... Covering message...
message "[You've been pickpocketed!]"
message "[You've been pickpocketed!]"

There's no obvious reason why this does or should work, but it does. :shrug: The message that is sent (including a blank message) will still display for the usual time, but messages that would ordinarily appear after it seem to be discarded -- i.e. they never enter the queue.

Con: The downside of this approach is that it may block more messages than you want to block. It basically nukes the queue for several frames -- any message sent by any script or action during that period will be lost.

OBSE Commands

As of version 0.15, OBSE has commands for adding/removing objects that do not generate spam.

See: AddItemNS, RemoveItemNS

Temp Container

When adding items to the player, spam can be avoided by first adding the item to a container, and then removing the contents from the container to the player. This works because unlike addItem, RemoveAllItems is silent.

tempContainerRef.addItem deathDagger 1
tempContainerRef.removeAllItems player 1

If you're using Cobl, you can use cobGenXFerRef for the temporary container -- it's defined for just this sort of use.

Item Activate

When adding items whose "activate" action results in being added to inventory (e.g. armor, but not books), you can use activate in a script.

someItemRef.activate player

Pro/Con: Requires that you have a ref for the item. On the plus side,this means that if you want the player to pick up a specific pre-existing, placed item, you can do that.