User:Nexii Malthus/Object-based health: Difference between revisions

From Second Life Wiki
Jump to navigation Jump to search
Nexii Malthus (talk | contribs)
Created page with "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 llGe..."
 
Nexii Malthus (talk | contribs)
No edit summary
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
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.
[[Category:LSL Combat2|Combat2]]


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


<syntaxhighlight lang="lsl2">
<syntaxhighlight lang="lsl2">
Line 8: 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 14: Line 21:
     {
     {
         float health = llGetHealth(llGetKey());
         float health = llGetHealth(llGetKey());
         while(count --> 0)
         integer deadlyDamage = -1;
        integer index;
        for(index = 0; index < count; ++index)
         {
         {
             list damage = llDetectedDamage(count);
             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;
         }
         }
          
          
         if(health < 0) health = 0;
         // Update the scripted health and set a useful hovertext
         else if(health > 300.0) health = 300.0;
         llSetLinkPrimitiveParamsFast(LINK_THIS, [
            PRIM_HEALTH, health,
            PRIM_TEXT, (string)llRound(health) + "/300", <0,1,0>, 1
        ]);
          
          
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_HEALTH, health]);
          
          
         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 35: Line 76:
     {
     {
         // We are dead, jim
         // We are dead, jim
        llSetText("dead", <1,0,0>, 1);
     }
     }
}
}
</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 02: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);
    }
}