Difference between revisions of "Combat Log"
(→Example Messages: Latest damage/death event examples. Pos seem to be numbers now) |
|||
Line 123: | Line 123: | ||
|} | |} | ||
==Example Messages== | ==Example Messages== | ||
Below is an example of a system generated combat log message, featuring a DAMAGE event following by a DEATH event: | Below is an example of a system generated combat log message, featuring a <code>DAMAGE</code>event following by a <code>DEATH</code>event: | ||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
Line 166: | Line 161: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
A DAMAGE event which features a damage adjustment: | A <code>DAMAGE</code>event which features a damage adjustment: | ||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
Line 203: | Line 198: | ||
// Script example with a listener and showing how to filter for damage events | // Script example with a listener and showing how to filter for damage events | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==Writing to Combat Log== | |||
If a region allows writing to combat logs it's recommended to pass messages in the same format as a JSON array of objects. | |||
<syntaxhighlight lang="lsl2"> | |||
string exampleEventObject = llList2Json(JSON_OBJECT, [ | |||
"event", "MY_CUSTOM_EVENT" | |||
]); | |||
list payloads = [exampleEventObject]; | |||
string message = llList2Json(JSON_ARRAY, payloads); | |||
llRegionSay(COMBAT_CHANNEL, message); | |||
</syntaxhighlight> | |||
If your messages are more auxiliary/extra it might be better to send them on <code>COMBAT_CHANNEL - 1</code> as there is no easy way to filter types of messages without parsing each (or otherwise only listening to system-generated messages) if you wish to make sure all scripts that listen on the combat log are responsive and not parsing unnecessary messages. | |||
A useful message to send into the combat log could be an <code>OBJECT_DEATH</code> message. [[DAMAGEABLE]] objects don't generate system messages when their health is reduced to 0 as the health is entirely managed and responsibility of the script with the damage processing events. | |||
The <code>OBJECT_DEATH</code>message should look the same as a <code>DEATH</code>message: | |||
{| {{Prettytable}} | |||
|+ JSON structure of a OBJECT_DEATH event | |||
|- {{Hl2}} | |||
! '''Key''' | |||
! '''Value''' | |||
! '''Description''' | |||
|- | |||
| "event" | |||
| "OBJECT_DEATH" | |||
| Object-generated message written into the [[COMBAT_CHANNEL]] declaring that the object had died | |||
|- | |||
| "type" | |||
| [[JSON_NUMBER]] | |||
| [[:Template:LSL_Constants/Damage_Types|DAMAGE_TYPE_*]] or any number defined by the scripter of the damage source | |||
|- | |||
| "source" | |||
| [[JSON_STRING]] | |||
| UUID key of damage source | |||
|- | |||
| "source_pos" | |||
| [[JSON_ARRAY]] | |||
| Array representing the position of the damage source | |||
|- | |||
| "target" | |||
| [[JSON_STRING]] | |||
| UUID key of damage target | |||
|- | |||
| "target_pos" | |||
| [[JSON_ARRAY]] | |||
| Array representing the position of the damage target | |||
|- | |||
| "owner" | |||
| [[JSON_STRING]] | |||
| UUID key of damage source owner | |||
|- | |||
| "rezzer" | |||
| [[JSON_STRING]] | |||
| UUID key of damage source rezzer | |||
|- | |||
|} | |||
Generating and sending the message taken from an [[User:Nexii_Malthus/Object-based_health|example object-based health script]]: | |||
<syntaxhighlight lang="lsl2"> | |||
// deadlyDamage is the number of the damage that caused the object to die in final_damage when health <= 0 | |||
// Generate synthetic object death event as per https://wiki.secondlife.com/wiki/Talk:Combat_Log#Damageable_Object_Deaths | |||
vector sourcePos = llDetectedPos(deadlyDamage); | |||
vector targetPos = llGetPos(); | |||
llRegionSay(COMBAT_CHANNEL, llList2Json(JSON_ARRAY, [ | |||
llList2Json(JSON_OBJECT, [ | |||
"event", "OBJECT_DEATH", | |||
"owner", llDetectedOwner(deadlyDamage), | |||
"rezzer", llDetectedRezzer(deadlyDamage), | |||
"source", llDetectedKey(deadlyDamage), | |||
"source_pos", llList2Json(JSON_ARRAY, [sourcePos.x, sourcePos.y, sourcePos.z]), | |||
"target", llGetKey(), | |||
"target_pos", llList2Json(JSON_ARRAY, [targetPos.x, targetPos.y, targetPos.z]), | |||
"type", llList2Integer(llDetectedDamage(deadlyDamage), 1) | |||
]) | |||
])); | |||
</syntaxhighlight> | |||
[[Category:LSL_Combat2]] | [[Category:LSL_Combat2]] |
Revision as of 21:52, 11 August 2024
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
This article has been classified as a stub, you can help the Second Life Wiki by expanding this article and adding more information.
The Combat Log has been added as part of the Combat2 update which allows for auditing and useful usecases.
- Combat Log messages are sent region-wide on the channel: COMBAT_CHANNEL
- Records all damage events, damage adjustments and kills
- System generated messages by a specific ID that scripts may filter to: COMBAT_LOG_ID
- Scripts may write to this channel if not restricted by the region, check via:
llGetEnv("restrict_combat_log")
System generated messages can be delayed up to 1 second as the sim collects messages to send them in bulk at a time.
Unless you want to intentionally listen to object generated messages it is recommended to set your listener to filter by COMBAT_LOG_ID, e.g. llListen(COMBAT_CHANNEL, "", COMBAT_LOG_ID, "");
This is because your script may end up unnecessarily receiving and processing custom messages that it was not designed to handle and ends up ignoring.
Message Format
The format of the combat log message is a JSON array ([]
) containing JSON objects ([{},{},{}]
). There is always an "event" property present to describe the type of the message object for parsing. The schema of the different objects are as follows:
Key | Value | Description | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
"event" | "DAMAGE" | ||||||||||
"damage" | JSON_NUMBER | Float of final damage applied | |||||||||
"initial" | JSON_NUMBER | Float of initial damage before adjustment | |||||||||
"type" | JSON_NUMBER | DAMAGE_TYPE_* or any number defined by the scripter of the damage source | |||||||||
"source" | JSON_STRING | UUID key of damage source | |||||||||
"target" | JSON_STRING | UUID key of damage target | |||||||||
"owner" | JSON_STRING | UUID key of damage source owner | |||||||||
"rezzer" | JSON_STRING | UUID key of damage source rezzer | |||||||||
"modifications" | JSON_ARRAY | Array of damage adjustments
|
Key | Value | Description |
---|---|---|
"event" | "DEATH" | |
"type" | JSON_NUMBER | DAMAGE_TYPE_* or any number defined by the scripter of the damage source |
"source" | JSON_STRING | UUID key of damage source |
"source_pos" | JSON_ARRAY | Array representing the position of the damage source |
"target" | JSON_STRING | UUID key of damage target |
"target_pos" | JSON_ARRAY | Array representing the position of the damage target |
"owner" | JSON_STRING | UUID key of damage source owner |
"rezzer" | JSON_STRING | UUID key of damage source rezzer |
Example Messages
Below is an example of a system generated combat log message, featuring a DAMAGE
event following by a DEATH
event:
[
{
"damage": 100,
"event": "DAMAGE",
"initial": 100,
"owner": "75078730-ebc8-4a80-adb9-1cfd2d95b5ca",
"rezzer": "7061ebe8-6919-49fd-8d9e-06983ada3108",
"source": "4daf361b-5912-e8f6-455c-ea9cdf0f0422",
"target": "75078730-ebc8-4a80-adb9-1cfd2d95b5ca",
"type": 102
},
{
"event": "DEATH",
"owner": "75078730-ebc8-4a80-adb9-1cfd2d95b5ca",
"rezzer": "7061ebe8-6919-49fd-8d9e-06983ada3108",
"source": "4daf361b-5912-e8f6-455c-ea9cdf0f0422",
"source_pos": [
52.5,
210.2584991455078,
1001.904296875
],
"target": "75078730-ebc8-4a80-adb9-1cfd2d95b5ca",
"target_pos": [
52.88808059692383,
210.6649627685547,
1001.1831665039062
],
"type": 102
}
]
A DAMAGE
event which features a damage adjustment:
{
"damage": 15.000000953674316,
"event": "DAMAGE",
"initial": 25,
"modifications": [
{
"events": [
{
"new_damage": 15.000000953674316,
"script": "Damage Adjustment Testing"
}
],
"task_id": "9d980b7e-9c74-a790-001c-bb852f95c16e"
}
],
"owner": "75078730-ebc8-4a80-adb9-1cfd2d95b5ca",
"rezzer": "75078730-ebc8-4a80-adb9-1cfd2d95b5ca",
"source": "daf3a6cb-8a56-afa9-5ebf-2156272dde16",
"target": "75078730-ebc8-4a80-adb9-1cfd2d95b5ca",
"type": 102
}
Parsing Messages
You can use JSON functions to help parse the messages:
// Script example with a listener and showing how to filter for death events
// Script example with a listener and showing how to filter for damage events
Writing to Combat Log
If a region allows writing to combat logs it's recommended to pass messages in the same format as a JSON array of objects.
string exampleEventObject = llList2Json(JSON_OBJECT, [
"event", "MY_CUSTOM_EVENT"
]);
list payloads = [exampleEventObject];
string message = llList2Json(JSON_ARRAY, payloads);
llRegionSay(COMBAT_CHANNEL, message);
If your messages are more auxiliary/extra it might be better to send them on COMBAT_CHANNEL - 1
as there is no easy way to filter types of messages without parsing each (or otherwise only listening to system-generated messages) if you wish to make sure all scripts that listen on the combat log are responsive and not parsing unnecessary messages.
A useful message to send into the combat log could be an OBJECT_DEATH
message. DAMAGEABLE objects don't generate system messages when their health is reduced to 0 as the health is entirely managed and responsibility of the script with the damage processing events.
The OBJECT_DEATH
message should look the same as a DEATH
message:
Key | Value | Description |
---|---|---|
"event" | "OBJECT_DEATH" | Object-generated message written into the COMBAT_CHANNEL declaring that the object had died |
"type" | JSON_NUMBER | DAMAGE_TYPE_* or any number defined by the scripter of the damage source |
"source" | JSON_STRING | UUID key of damage source |
"source_pos" | JSON_ARRAY | Array representing the position of the damage source |
"target" | JSON_STRING | UUID key of damage target |
"target_pos" | JSON_ARRAY | Array representing the position of the damage target |
"owner" | JSON_STRING | UUID key of damage source owner |
"rezzer" | JSON_STRING | UUID key of damage source rezzer |
Generating and sending the message taken from an example object-based health script:
// deadlyDamage is the number of the damage that caused the object to die in final_damage when health <= 0
// Generate synthetic object death event as per https://wiki.secondlife.com/wiki/Talk:Combat_Log#Damageable_Object_Deaths
vector sourcePos = llDetectedPos(deadlyDamage);
vector targetPos = llGetPos();
llRegionSay(COMBAT_CHANNEL, llList2Json(JSON_ARRAY, [
llList2Json(JSON_OBJECT, [
"event", "OBJECT_DEATH",
"owner", llDetectedOwner(deadlyDamage),
"rezzer", llDetectedRezzer(deadlyDamage),
"source", llDetectedKey(deadlyDamage),
"source_pos", llList2Json(JSON_ARRAY, [sourcePos.x, sourcePos.y, sourcePos.z]),
"target", llGetKey(),
"target_pos", llList2Json(JSON_ARRAY, [targetPos.x, targetPos.y, targetPos.z]),
"type", llList2Integer(llDetectedDamage(deadlyDamage), 1)
])
]));