Difference between revisions of "User:Nexii Malthus/Object-based health"
(4 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
[[Category:LSL Combat2|Combat2]] | [[Category:LSL Combat2|Combat2]] | ||
This is pretty much as simple as it gets. No damage adjustment, just processing final damage. We initialise with a set amount of health which other scripts can read via [[llGetHealth]]. The presence of the [[final_damage]] event marks this as a DAMAGEABLE object for sensors and collisions. | This is pretty much as simple as it gets. No damage adjustment, just processing final damage. We initialise with a set amount of health which other scripts can read via [[llGetHealth]]. The presence of the [[final_damage]] event marks this as a [[DAMAGEABLE]] object for sensors and collisions. | ||
For object-based health the script needs to manually manage it's own health, applying the final damage to the health amount and setting the objects health. | For object-based health the script needs to manually manage it's own health, applying the final damage to the health amount and setting the objects health. If the health reaches 0 or below during the damage processing, it should be considered dead and stop further processing. | ||
Because objects don't generate death events, whether the on_death or the system generated combat log messages, we have to handle that aspect ourselves. A community proposals is to send a synthetic OBJECT_DEATH event into the combat channel. | |||
<syntaxhighlight lang="lsl2"> | <syntaxhighlight lang="lsl2"> | ||
Line 10: | Line 12: | ||
state_entry() | state_entry() | ||
{ | { | ||
llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_HEALTH, 300.0]); | llSetLinkPrimitiveParamsFast(LINK_THIS, [ | ||
PRIM_HEALTH, 300.0, | |||
PRIM_TEXT, "300/300", <0,1,0>, 1 | |||
]); | |||
} | } | ||
Line 16: | Line 21: | ||
{ | { | ||
float health = llGetHealth(llGetKey()); | float health = llGetHealth(llGetKey()); | ||
integer deadlyDamage = -1; | |||
integer index; | |||
for(index = 0; index < count; ++index) | |||
{ | { | ||
list damage = llDetectedDamage( | list damage = llDetectedDamage(index); | ||
float amount = llList2Float(damage, 0); | float amount = llList2Float(damage, 0); | ||
health -= amount; | health -= amount; | ||
// Check which damage dealt a deadly blow and break the loop | |||
if(health <= 0) | |||
{ | |||
health = 0; | |||
deadlyDamage = index; | |||
index = count; | |||
} | |||
// Prevent overhealing | |||
else if(health > 300.0) health = 300.0; | |||
} | } | ||
// Update the scripted health and set a useful hovertext | |||
llSetLinkPrimitiveParamsFast(LINK_THIS, [ | |||
PRIM_HEALTH, health, | |||
PRIM_TEXT, (string)llRound(health) + "/300", <0,1,0>, 1 | |||
]); | |||
if(health == 0) state dead; | if(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) | |||
]) | |||
])); | |||
state dead; | |||
} | |||
} | } | ||
} | } | ||
Line 37: | Line 76: | ||
{ | { | ||
// We are dead, jim | // We are dead, jim | ||
llSetText("dead", <1,0,0>, 1); | |||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |
Latest revision as of 01:09, 11 August 2024
This is pretty much as simple as it gets. No damage adjustment, just processing final damage. We initialise with a set amount of health which other scripts can read via llGetHealth. The presence of the final_damage event marks this as a DAMAGEABLE object for sensors and collisions.
For object-based health the script needs to manually manage it's own health, applying the final damage to the health amount and setting the objects health. If the health reaches 0 or below during the damage processing, it should be considered dead and stop further processing.
Because objects don't generate death events, whether the on_death or the system generated combat log messages, we have to handle that aspect ourselves. A community proposals is to send a synthetic OBJECT_DEATH event into the combat channel.
default
{
state_entry()
{
llSetLinkPrimitiveParamsFast(LINK_THIS, [
PRIM_HEALTH, 300.0,
PRIM_TEXT, "300/300", <0,1,0>, 1
]);
}
final_damage(integer count)
{
float health = llGetHealth(llGetKey());
integer deadlyDamage = -1;
integer index;
for(index = 0; index < count; ++index)
{
list damage = llDetectedDamage(index);
float amount = llList2Float(damage, 0);
health -= amount;
// Check which damage dealt a deadly blow and break the loop
if(health <= 0)
{
health = 0;
deadlyDamage = index;
index = count;
}
// Prevent overhealing
else if(health > 300.0) health = 300.0;
}
// Update the scripted health and set a useful hovertext
llSetLinkPrimitiveParamsFast(LINK_THIS, [
PRIM_HEALTH, health,
PRIM_TEXT, (string)llRound(health) + "/300", <0,1,0>, 1
]);
if(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)
])
]));
state dead;
}
}
}
state dead
{
state_entry()
{
// We are dead, jim
llSetText("dead", <1,0,0>, 1);
}
}