Difference between revisions of "Message Spam"

1,793 bytes removed ,  09:17, 17 November 2012
Updated information on OBSE spamless functions
imported>DragoonWraith
(bylined)
imported>QQuix
(Updated information on OBSE spamless functions)
 
(9 intermediate revisions by 3 users not shown)
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:
===AddItem - aTemp 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</pre>


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.
If you're using [[Glossary#C|Cobl]], you can use '''cobGenXFerRef''' for the temporary container -- it's defined for just this sort of use.


'''Note:''' Do ''not'' wait a frame to remove the item to the player. If you do, you run the chance of running the item's script, which in rare circumstances can cause problems.
===Message Queue Overloading===
Simplest technique is to overload the message queue by sending the exact same message twice in a row <i>before</i> the offending add or remove line, <i>i.e.</i>
<pre>;--No messages.
<pre>;--No messages.
message " "
message " "
message " "
message " "
addItem myItem, 1


;--OR... Covering message...
;--OR... Covering message...
message "[You've been pickpocketed!]"
message "[You've been pickpocketed!]"
message "[You've been pickpocketed!]"</pre>
message "[You've been pickpocketed!]"
 
addItem myItem, 1</pre>
----
 
 
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:
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.


scn MyAddItemScript
'''Con:''' The downside of this approach is that it may block more messages than you want to block. It basically nukes the queue for a second or two -- any message sent by any script or action during that period will be lost.
; 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:
'''Con:''' Some UI mods add an Oblivion icon for all messages. This icon will still appear for the duration of the message - defeating the purpose of the blank message.


; some script - example
===OBSE Commands===
set MyAddItemFunc.numItems to 1+0.1*GetRandomPercent; 1-10 for number
OBSE provides the following spam free versions as alternatives for vanilla functions that generate spam messages and sound:
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.


-----------------------
These two functions do not span messages when adding and removing spells:
*[[AddSpellNS]]
*[[RemoveSpellNS]]


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.
These two functions do not span messages when equipping and unequipping:
*[[EquipItemNS]]
*[[UnequipItemNS]]


Begin GameMode
...
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:
These functions do not span messages and do not generate the corresponding sound:
*[[AddItemNS]]
*[[RemoveItemNS]]
*[[EquipItemSilent]]
*[[UnequipItemSilent]]


set MyQuest.RemoveMyItem to player.GetItemCount MyItem


More general notes as FYI:


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.


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.
Anonymous user