diff --git a/LBH Slim v1.2.2.lsl b/LBH/LBH Slim v1.2.5.lsl similarity index 84% rename from LBH Slim v1.2.2.lsl rename to LBH/LBH Slim v1.2.5.lsl index 3887489..de4a3e7 100644 --- a/LBH Slim v1.2.2.lsl +++ b/LBH/LBH Slim v1.2.5.lsl @@ -5,15 +5,16 @@ integer hp=mhp;//Current HP //Negative Numbers Restore Health integer atcap=50; //Damage Processor -damage(integer amt, key id,vector pos, vector targetPos) +damage(integer amt, key id) { if(amt>atcap)amt=atcap; if(amt<0)//Allows the object to be healed/repaired { if(llGetTime()>1.0)//Optional healing cooldown { + amt*=-1; if(amt>(float)hp*0.1)amt=llRound((float)hp*0.1);//Optional healing cap - hp-=amt; + hp+=amt; if(hp>mhp)hp=mhp;//Used to prevent overhealing llResetTime(); } @@ -33,7 +34,7 @@ damage(integer amt, key id,vector pos, vector targetPos) update()//SetText { llSetLinkPrimitiveParamsFast(-4,[PRIM_TEXT,"[LBHS]\n "+(string)hp+" / "+(string)mhp+" HP",<1.0,1.0,1.0>,1.0, - PRIM_DESC,"LBA.v.LBHS,"+(string)hp+","+(string)mhp+","+(string)atcap+",666"]); + PRIM_DESC,"LBA.v.HS,"+(string)hp+","+(string)mhp+","+(string)atcap+",666"]); //In order: Current HP, Max HP, Max AT accepted, Max healing accepted (Not implemented) } die() @@ -83,11 +84,9 @@ default list parse=llParseString2List(message,[","],[" "]); if(llList2Key(parse,0)==me)//targetcheck { - vector pos=llGetPos(); - vector targetPos=tar(id); float amt=llList2Float(parse,-1); - if(llFabs(amt)<666.0)damage((integer)amt,id,pos,targetPos);//Use this code to allow object healing, Blocks overflow attempts - //if(amt>0)damage((integer)amt,id,pos,targetPos);//Use this code if you do not wish to support healing + if(llFabs(amt)<666.0)damage((integer)amt,id);//Use this code to allow object healing, Blocks overflow attempts + //if(amt>0)damage((integer)amt,id);//Use this code if you do not wish to support healing } } collision_start(integer c)//Enable this block if you want to support legacy collisions. diff --git a/LBH/LBH-AG v1.2.5.lsl b/LBH/LBH-AG v1.2.5.lsl new file mode 100644 index 0000000..6f44189 --- /dev/null +++ b/LBH/LBH-AG v1.2.5.lsl @@ -0,0 +1,171 @@ +//AG Variant includes a built-in anti-grief and blacklisting system. See line 49+ for details. +integer mhp=100;//Maximum HP +integer hp=mhp;//Current HP +//Positive Numbers Deal Damage +//Negative Numbers Restore Health +integer atcap=50; +//Damage Processor +damage(integer amt, key id) +{ + if(amt>atcap)amt=atcap; + if(amt<0)//Allows the object to be healed/repaired + { + if(llGetTime()>1.0)//Optional healing cooldown + { + amt*=-1; + if(amt>(float)hp*0.1)amt=llRound((float)hp*0.1);//Optional healing cap + hp+=amt; + if(hp>mhp)hp=mhp;//Used to prevent overhealing + llResetTime(); + } + //Be sure to update the listen event code block to allow negative damage values through. + } + /*else if(amt<6)return; //Blocks micro-LBA*/ + else if(amt) + { + if(amt>atcap)amt=atcap; + hp-=amt; + } + else return; + if(hp<1)die(); + else update(); +} + +update()//SetText +{ + llSetLinkPrimitiveParamsFast(-4,[PRIM_TEXT,"[LBH-AG]\n "+(string)hp+" / "+(string)mhp+" HP",<1.0,1.0,1.0>,1.0, + PRIM_DESC,"LBA.v.HAG,"+(string)hp+","+(string)mhp+","+(string)atcap+",666"]); + //In order: Current HP, Max HP, Max AT accepted, Max healing accepted (Not implemented) +} +die() +{ + //Add extra shit here + //llResetScript();//Debug + llDie();//Otherwise, use this +} +vector tar(key id) +{ + vector av=(vector)((string)llGetObjectDetails(id,[OBJECT_POS])); + return av; +} +//Anti-Grief +float interval=2.0;//How many seconds before the threshold is cleared. Recommended 2 seconds. +integer banthresh=80;//How much HP within the interval is considered ban worth, this affects single-hits as well as ATCAP is used only during damage calculations. Note that exceeding the ATCAP will still count against the user as the difference is not factored with the tracker. +//With a 2s interval at 80 damage, it will require a single owner to deal more than 40 DPS in order to get blacklisted. +list banlist; +//Tracker stores information like so: OWNER_UUID,DMG_TRACKED +list tracker; +integer checkdmg(string source, key owner, integer amt)//0 = Do not take damage, 1 = Take damage +{ + if(llListFindList(banlist,[owner])>-1)return 0;//Checks for previously banned source + else + { + integer param=llListFindList(banlist,[owner]); + if(param>-1)//Owner damage is already in tracker. + { + integer totalamt=llList2Integer(tracker,param+1); + if(totalamtmhp)hp=mhp; + return 0; + } + } + else + { + if(amt>banthresh) + { + banlist+=owner; + llOwnerSay("Banned "+llKey2Name(owner)+" for dealing "+(string)amt+" damage + Last source: ["+source+"] for "+(string)amt+" damage"); + llRegionSayTo(owner,0,"Blacklisted for dealing too much damage too quickly"); + return 0; + //No need to refund damage since they were not already in tracker + } + else + { + tracker+=[owner,amt]; + return 1; + } + } + } +} +// +key user; +key gen;//Object rezzer +key me; +integer hear; +boot() +{ + user=llGetOwner(); + me=llGetKey(); + gen=(string)llGetObjectDetails(me,[OBJECT_REZZER_KEY]); + if(hear)llListenRemove(hear); + integer hex=(integer)("0x" + llGetSubString(llMD5String((string)me,0), 0, 3)); + hear=llListen(hex,"","",""); + llSetTimerEvent(interval); + update(); +} +default +{ + state_entry() + { + boot(); + } + on_rez(integer p) + { + if(p>1)//Allows HUD/Objects to set HP value when rezzed with a param, otherwise uses default + { + mhp=p; + hp=p; + } + boot(); + } + listen(integer chan, string name, key id, string message) + { + //[ALWAYS] USE llRegionSayTo(). Do not flood the channel with useless garbage that'll poll every object in listening range. + list parse=llParseString2List(message,[","],[" "]); + if(llList2Key(parse,0)==me)//targetcheck + { + integer amt=llList2Integer(parse,-1); + if(llFabs(amt)<666.0)//Overflow check + { + if(amt>0.0) + { + if(checkdmg(name,llGetOwnerKey(id),amt)) + { + llSetTimerEvent(interval);//Reset interval on new damage update + damage(amt,id); + } + } + else damage(amt,id); + } + } + } + collision_start(integer c)//Enable this block if you want to support legacy collisions. + { + if(llVecMag(llDetectedVel(0))>40.0) + { + hp-=c; + if(hp<1)die();//llDie(); + else update(); + } + } + timer() + { + tracker=[];//Clear tracker + //Auto-Deleter + if(tar(gen))return; + llDie(); + } +} diff --git a/LBH/LBHD+AG, Directional Armor v1.4.3.lsl b/LBH/LBHD+AG, Directional Armor v1.4.3.lsl new file mode 100644 index 0000000..08361d7 --- /dev/null +++ b/LBH/LBHD+AG, Directional Armor v1.4.3.lsl @@ -0,0 +1,248 @@ +string ver="DHAGv1.4.3";//LBA Version +integer mhp=200;//Maximum HP +integer hp=mhp;//Current HP +//Anti-Grief +float interval=1.0;//How many seconds before the threshold is cleared. +integer banthresh=250;//How much HP within the interval is considered ban worth, this affects single-hits as well as ATCAP is used only during damage calculations. Note that exceeding the ATCAP will still count against the user as the difference is not factored with the tracker. +//With a 2s interval at 80 damage, it will require a single owner to deal more than 40 DPS in order to get blacklisted. +list banlist; +//Tracker stores information like so: OWNER_UUID,DMG_TRACKED +list bantracker; +integer checkdmg(string source, key owner, integer amt)//0 = Do not take damage, 1 = Take damage +{ + if(llListFindList(banlist,[owner])>-1)return 0;//Checks for previously banned source + else + { + integer param=llListFindList(banlist,[owner]); + if(param>-1)//Owner damage is already in tracker. + { + integer totalamt=llList2Integer(tracker,param+1); + if(totalamtmhp)hp=mhp; + return 0; + } + } + else + { + bantracker+=[owner,amt]; + return 1; + } + } +} +//Positive Numbers Deal Damage +//Negative Numbers Restore Health +//Damage Multipliers: 0 = Invulnerable, 1.0 = 100% Damage, High numbers = Higher Damage +//The total between all values should be around 5.0 for balancing purposes. +integer atcap=200; +float front=0.5; +float side=1.0; +float back=1.5; +float middle=0.1; +//Note that following modifiers multiply the final damage. So it stacks multiplicatively with the previous modifiers +float top=1.2; +float bottom=1.2; +//Directional Processor +float front_threshold=25.0;//Use positive floats, determines forward range +float back_threshold=155.0;//Use positive floats, determines backward range +float top_threshold=0.75;//How far up the Z axis should the source be to registered a top. (Positive Number) +float bottom_threshold=-0.75;//How far down the Z axis should the source be to registered a bottom hit. (Negative Number) +float collisionmod(vector pos, vector targetPos) +{ + if(targetPos) + { + float dist=llVecDist(pos,targetPos); + if(dist<1.0)return middle;//This catches explosions which rezzes AT in the object's root position. + else + { + vector fpos=(targetPos-pos)/llGetRot(); + float mod=fpos.z; + if(mod>=top_threshold)mod=top;//Top check + else if(mod<=bottom_threshold)mod=bottom;//Bottom check + else mod=1.0;//Else reset it to 1.0 + vector angle=<1.0,0.0,0.0>*llGetRot(); + angle.z=0.0; + rotation targetRot=llRotBetween(llVecNorm(angle),llVecNorm(-pos)); + vector targetRotVec=llRot2Euler(targetRot)*RAD_TO_DEG; + if(targetRotVec.z>-front_threshold&&targetRotVec.zback_threshold)//Back + return back*mod; + else //If it didn't hit any previous angles, the only thing left to hit is the sides. + return side*mod; + } + } + else return 0.0; +} +//Damage Processor +damage(integer amt, key id,vector pos, vector targetPos, float tmod,string name) +{ + if(amt>atcap)amt=atcap; + if(amt<0)//Allows the object to be healed/repaired + { + if(llGetTime()>1.0)//Optional healing cooldown + { + amt*=-1.0; + if(amt>(float)hp*0.1)amt=llRound(hp*0.1);//Optional healing cap + hp+=amt; + if(hp>mhp)hp=mhp;//Used to prevent overhealing + llResetTime(); + } + //Be sure to update the listen event code block to allow negative damage values through. + } + /*else if(amt<6)return; //Blocks micro-LBA*/ + else + { + integer directional_amt; + if(tmod)directional_amt=llFloor(amt*tmod); + else directional_amt=llFloor(collisionmod(pos,targetPos)*(float)amt); + if(directional_amt)hp-=directional_amt; + else //Failed to do damage + { + llOwnerSay("Damage Blocked by Armor"); + llRegionSayTo(llGetOwnerKey(id),0,"Attack was stopped by armor."); + return; + } + llOwnerSay("/me took "+(string)directional_amt+" ("+(string)amt+") damage from "+name+" by "+llKey2Name(llGetOwnerKey(id)));//Used to debug output. + llRegionSayTo(llGetOwnerKey(id),0,"/me took "+(string)directional_amt+" ("+(string)amt+") damage"); + } + if(hp<1)die(); + else update(); +} +string modifierstring;//This is visible so moderators can confirm vehicle attributes are within regulation. +update()//SetText +{ + llSetLinkPrimitiveParamsFast(-4,[PRIM_TEXT,"[LBHD]\n "+(string)hp+" / "+(string)mhp+" HP",<0.0,0.75,1.0>,1.0, + PRIM_DESC,"LBA.v."+ver+","+(string)hp+","+(string)mhp+","+(string)atcap+",999"+modifierstring]); + //In order: Current HP, Max HP, Max AT accepted, Max healing accepted (Not implemented) +} +die() +{ + //Add extra shit here + //llResetScript();//Debug + llDie();//Otherwise, use this +} +integer los(vector start, vector target)//1=LoS,0=Obstructed +{ + list ray=llCastRay(start,target,[RC_REJECT_TYPES,RC_REJECT_AGENTS,RC_DATA_FLAGS,RC_GET_ROOT_KEY,RC_MAX_HITS,1]); + if(llList2Vector(ray,1)==ZERO_VECTOR)return 1; + else return 0; +} +vector tar(key id)//Deprecated +{ + vector av=(vector)((string)llGetObjectDetails(id,[OBJECT_POS])); + return av; +} +key user; +key gen;//Object rezzer +key me; +integer hear; +list tracker; +boot() +{ + modifierstring=",F-"+llGetSubString((string)front,0,2)+//Frontal modifier + ",S-"+llGetSubString((string)side,0,2)+//Side modifier + ",R-"+llGetSubString((string)back,0,2)+//Rear modifier + ",T-"+llGetSubString((string)top,0,2)+//Top modifier + ",B-"+llGetSubString((string)bottom,0,2)+//Bottom modifier + ",M-"+llGetSubString((string)middle,0,2);//Middle Modifier + user=llGetOwner(); + me=llGetKey(); + gen=(string)llGetObjectDetails(me,[OBJECT_REZZER_KEY]); + if(hear)llListenRemove(hear); + integer hex=(integer)("0x" + llGetSubString(llMD5String((string)me,0), 0, 3)); + hear=llListen(hex,"","",""); + llSetTimerEvent(interval); + update(); +} +default +{ + state_entry() + { + boot(); + } + on_rez(integer p) + { + if(p>1)//Allows HUD/Objects to set HP value when rezzed with a param, otherwise uses default + { + mhp=p; + hp=p; + } + boot(); + } + listen(integer chan, string name, key id, string message) + { + //[ALWAYS] USE llRegionSayTo(). Do not flood the channel with useless garbage that'll poll every object in listening range. + list parse=llParseString2List(message,[","],[" "]); + if(llList2Key(parse,0)==me)//targetcheck + { + list data=llGetObjectDetails(id,[OBJECT_POS,OBJECT_ATTACHED_POINT,OBJECT_ROT,OBJECT_REZZER_KEY]); + vector pos=llGetPos(); + vector targetPos=llList2Vector(data,0); + float amt=llList2Float(parse,-1); + if(llFabs(amt)<666)//Use this code to allow object healing, Blocks overflow attempts + { + if(amt>0) + { + if(checkdmg(name,llGetOwnerKey(id),(integer)amt)) + { + float tmod; + integer f=llListFindList(tracker,[name]); + if(f>-1)tmod=llList2Float(tracker,f+1); + else //Rezzer rezzer's rezzer rezzer + { + f=llListFindList(tracker,[llList2Key(data,4)]); + if(f>-1)tmod=llList2Float(tracker,f+1); + } + llSetTimerEvent(interval);//Reset interval on new damage update + if(llList2Integer(data,1)) + { + float dist=llVecDist(targetPos,pos)-2.0; + vector posfix=targetPos+*llList2Rot(data,2); + if(los(pos,posfix))damage((integer)amt,id,pos,posfix,0.0,name); + else damage((integer)amt,id,pos,targetPos,0.0,name); + } + else damage((integer)amt,id,pos,targetPos,tmod,name); + } + } + else damage((integer)amt,id,pos,targetPos,0.0,name); + } + } + } + collision_start(integer c) + { + if(llVecMag(llDetectedVel(0))>40.0) + { + vector gpos=llGetPos(); + if(tracker==[])llSetTimerEvent(1.0); + string name=llDetectedName(0); + integer f=llListFindList(tracker,[name]); + if(f>-1)tracker=llListReplaceList(tracker,[collisionmod(gpos,llDetectedPos(0))],f+1,f+1); + else + { + if(llGetListLength(tracker)>10)tracker=llDeleteSubList(tracker,0,1);//Delete eldest entry to prevent stack-heap + tracker+=[name,collisionmod(gpos,llDetectedPos(0))]; + } + //Stores data as follows: OBJECT_NAME,OBJECT_MODIFIER + //Updates objects of the same name to the most recent. + } + } + timer() + { + bantracker=[]; + tracker=[];//Reset tracker + if(tar(gen))return;//Auto-deleter + llDie(); + } +} diff --git a/LBH/LBHD, Directional Armor v1.4.3.lsl b/LBH/LBHD, Directional Armor v1.4.3.lsl new file mode 100644 index 0000000..2254b99 --- /dev/null +++ b/LBH/LBHD, Directional Armor v1.4.3.lsl @@ -0,0 +1,199 @@ +string ver="DHv1.4.3";//LBA Version +integer mhp=200;//Maximum HP +integer hp=mhp;//Current HP +//Positive Numbers Deal Damage +//Negative Numbers Restore Health +//Damage Multipliers: 0 = Invulnerable, 1.0 = 100% Damage, High numbers = Higher Damage +//The total between all values should be around 5.0 for balancing purposes. +integer atcap=200; +float front=0.5; +float side=1.0; +float back=1.5; +float middle=0.1; +//Note that following modifiers multiply the final damage. So it stacks multiplicatively with the previous modifiers +float top=1.2; +float bottom=1.5; +//Directional Processor +float front_threshold=25.0;//Use positive floats, determines forward range +float back_threshold=155.0;//Use positive floats, determines backward range +float top_threshold=0.75;//How far up the Z axis should the source be to registered a top. (Positive Number) +float bottom_threshold=-0.75;//How far down the Z axis should the source be to registered a bottom hit. (Negative Number) +float collisionmod(vector pos, vector targetPos) +{ + if(targetPos) + { + float dist=llVecDist(pos,targetPos); + if(dist<1.0)return middle;//This catches explosions which rezzes AT in the object's root position. + else + { + vector fpos=(targetPos-pos)/llGetRot(); + float mod=fpos.z; + if(mod>=top_threshold)mod=top;//Top check + else if(mod<=bottom_threshold)mod=bottom;//Bottom check + else mod=1.0;//Else reset it to 1.0 + vector angle=<1.0,0.0,0.0>*llGetRot(); + angle.z=0.0; + rotation targetRot=llRotBetween(llVecNorm(angle),llVecNorm(-pos)); + vector targetRotVec=llRot2Euler(targetRot)*RAD_TO_DEG; + if(targetRotVec.z>-front_threshold&&targetRotVec.zback_threshold)//Back + return back*mod; + else //If it didn't hit any previous angles, the only thing left to hit is the sides. + return side*mod; + } + } + else return 0.0; +} +//Damage Processor +damage(integer amt, key id,vector pos, vector targetPos, float tmod, string name) +{ + if(amt>atcap)amt=atcap; + if(amt<0)//Allows the object to be healed/repaired + { + if(llGetTime()>1.0)//Optional healing cooldown + { + amt*=-1.0; + if(amt>(float)hp*0.1)amt=llRound(hp*0.1);//Optional healing cap + hp+=amt; + if(hp>mhp)hp=mhp;//Used to prevent overhealing + llResetTime(); + } + //Be sure to update the listen event code block to allow negative damage values through. + } + /*else if(amt<6)return; //Blocks micro-LBA*/ + else + { + integer directional_amt; + if(tmod)directional_amt=llFloor(amt*tmod); + else directional_amt=llFloor(collisionmod(pos,targetPos)*(float)amt); + if(directional_amt)hp-=directional_amt; + else //Failed to do damage + { + llOwnerSay("Damage Blocked by Armor"); + llRegionSayTo(llGetOwnerKey(id),0,"Attack was stopped by armor."); + return; + } + llOwnerSay("/me took "+(string)directional_amt+" ("+(string)amt+") damage from "+name+" by "+llKey2Name(llGetOwnerKey(id)));//Used to debug output. + llRegionSayTo(llGetOwnerKey(id),0,"/me took "+(string)directional_amt+" ("+(string)amt+") damage"); + } + if(hp<1)die(); + else update(); +} +string modifierstring;//This is visible so moderators can confirm vehicle attributes are within regulation. +update()//SetText +{ + llSetLinkPrimitiveParamsFast(-4,[PRIM_TEXT,"[LBHD]\n "+(string)hp+" / "+(string)mhp+" HP",<0.0,0.75,1.0>,1.0, + PRIM_DESC,"LBA.v."+ver+","+(string)hp+","+(string)mhp+","+(string)atcap+",999"+modifierstring]); + //In order: Current HP, Max HP, Max AT accepted, Max healing accepted (Not implemented) +} +die() +{ + //Add extra shit here + //llResetScript();//Debug + llDie();//Otherwise, use this +} +integer los(vector start, vector target)//1=LoS,0=Obstructed +{ + list ray=llCastRay(start,target,[RC_REJECT_TYPES,RC_REJECT_AGENTS,RC_DATA_FLAGS,RC_GET_ROOT_KEY,RC_MAX_HITS,1]); + if(llList2Vector(ray,1)==ZERO_VECTOR)return 1; + else return 0; +} +vector tar(key id)//Deprecated +{ + vector av=(vector)((string)llGetObjectDetails(id,[OBJECT_POS])); + return av; +} +key user; +key gen;//Object rezzer +key me; +integer hear; +list tracker; +boot() +{ + modifierstring=",F-"+llGetSubString((string)front,0,2)+//Frontal modifier + ",S-"+llGetSubString((string)side,0,2)+//Side modifier + ",R-"+llGetSubString((string)back,0,2)+//Rear modifier + ",T-"+llGetSubString((string)top,0,2)+//Top modifier + ",B-"+llGetSubString((string)bottom,0,2)+//Bottom modifier + ",M-"+llGetSubString((string)middle,0,2);//Middle Modifier + user=llGetOwner(); + me=llGetKey(); + gen=(string)llGetObjectDetails(me,[OBJECT_REZZER_KEY]); + if(hear)llListenRemove(hear); + integer hex=(integer)("0x" + llGetSubString(llMD5String((string)me,0), 0, 3)); + hear=llListen(hex,"","",""); + llSetTimerEvent(1.0);//Used for auto-delete. + update(); +} +default +{ + state_entry() + { + boot(); + } + on_rez(integer p) + { + if(p>1)//Allows HUD/Objects to set HP value when rezzed with a param, otherwise uses default + { + mhp=p; + hp=p; + } + boot(); + } + listen(integer chan, string name, key id, string message) + { + //[ALWAYS] USE llRegionSayTo(). Do not flood the channel with useless garbage that'll poll every object in listening range. + list parse=llParseString2List(message,[","],[" "]); + if(llList2Key(parse,0)==me)//targetcheck + { + list data=llGetObjectDetails(id,[OBJECT_POS,OBJECT_ATTACHED_POINT,OBJECT_ROT,OBJECT_REZZER_KEY]); + vector pos=llGetPos(); + vector targetPos=llList2Vector(data,0); + float tmod; + integer f=llListFindList(tracker,[name]); + if(f>-1)tmod=llList2Float(tracker,f+1); + else //Rezzer rezzer's rezzer rezzer + { + f=llListFindList(tracker,[llList2Key(data,4)]); + if(f>-1)tmod=llList2Float(tracker,f+1); + } + float amt=llList2Float(parse,-1); + if(llFabs(amt)<666.0) + { + if(llList2Integer(data,1)) + { + float dist=llVecDist(targetPos,pos)-2.0; + vector posfix=targetPos+*llList2Rot(data,2); + if(los(pos,posfix))damage((integer)amt,id,pos,posfix,0.0,name); + else damage((integer)amt,id,pos,targetPos,0.0,name); + } + else damage((integer)amt,id,pos,targetPos,tmod,name); + } + } + } + collision_start(integer c) + { + if(llVecMag(llDetectedVel(0))>40.0) + { + vector gpos=llGetPos(); + if(tracker==[])llSetTimerEvent(1.0); + string name=llDetectedName(0); + integer f=llListFindList(tracker,[name]); + if(f>-1)tracker=llListReplaceList(tracker,[collisionmod(gpos,llDetectedPos(0))],f+1,f+1); + else + { + if(llGetListLength(tracker)>10)tracker=llDeleteSubList(tracker,0,1);//Delete eldest entry to prevent stack-heap + tracker+=[name,collisionmod(gpos,llDetectedPos(0))]; + } + //Stores data as follows: OBJECT_NAME,OBJECT_MODIFIER + //Updates objects of the same name to the most recent. + } + } + timer()//Auto-deleter. Will kill object if avatar leaves the region or spawning object is removed. + { + tracker=[];//Reset tracker + if(tar(gen))return; + llDie(); + } +} diff --git a/LBH/LBHD-Component, v1.4.4.lsl b/LBH/LBHD-Component, v1.4.4.lsl new file mode 100644 index 0000000..1ed6d6c --- /dev/null +++ b/LBH/LBHD-Component, v1.4.4.lsl @@ -0,0 +1,315 @@ +//MBTLBA was a stupid name +string ver="DHCv1.4.4";//LBA Version +//efx +integer burning;//burning flag +integer repair;//repair timer +integer detrack;//detrack flah +integer layer;//detrack layers +integer ml;//Mouselook tracker +integer emk;//em kit +// +integer mhp=250;//Maximum HP +integer hp=mhp;//Current HP +//Positive Numbers Deal Damage +//Negative Numbers Restore Health +//Damage Multipliers: 0 = Invulnerable, 1.0 = 100% Damage, High numbers = Higher Damage +integer atcap=500; +float front=0.5; +float side=1.0; +float back=1.5; +float middle=0.1; +//Note that following modifiers multiply the final damage. So it stacks multiplicatively with the previous modifiers +float top=1.2; +float bottom=1.2; +//Directional Processor +float front_threshold=20.0;//Use positive floats, determines forward range +float back_threshold=160.0;//Use positive floats, determines backward range +float top_threshold=0.75;//How far up the Z axis should the source be to registered a top. (Positive Number) +float bottom_threshold=-0.75;//How far down the Z axis should the source be to registered a bottom hit. (Negative Number) +vector collisionmod(vector pos, vector targetPos) +{ + if(targetPos) + { + float trak; + float dist=llVecDist(pos,targetPos); + if(dist<1.0)return <0.01,0.0,0.0>;//This catches explosions which rezzes AT in the object's root position. + else + { + vector fpos=(targetPos-pos)/llGetRot(); + float mod=fpos.z; + if(mod>=top_threshold)mod=top;//Top check + else if(mod<=bottom_threshold) + { + ++trak;//Chance to detrack + mod=bottom;//Bottom check + } + else mod=1.0;//Else reset it to 1.0 + vector angle=<1.0,0.0,0.0>*llGetRot(); + angle.z=0.0; + rotation targetRot=llRotBetween(llVecNorm(angle),llVecNorm(-pos)); + vector targetRotVec=llRot2Euler(targetRot)*RAD_TO_DEG; + if(targetRotVec.z>-front_threshold&&targetRotVec.z; + else if(targetRotVec.z<-back_threshold||targetRotVec.z>back_threshold)return ;//chance to burn + else return ; + } + } + else return ZERO_VECTOR; +} +//Damage Processor +damage(integer amt, key id,vector pos, vector targetPos,vector tmod,string name) +{ + //Tmod Dump: Damage modifier, Did I detrack?, Did I burn? + if(amt>atcap)amt=atcap; + if(amt<0)//Allows the object to be healed/repaired + { + if(llGetTime()>1.0)//Optional healing cooldown + { + if(burning||detrack) + { + burning=0; + detrack=0; + llMessageLinked(-4,1,"",""); + llOwnerSay("Status Repaired"); + } + amt*=-1.0; + if(amt>(float)hp*0.1)amt=llRound(hp*0.1);//Optional healing cap + hp+=amt; + if(hp>mhp)hp=mhp;//Used to prevent overhealing + llResetTime(); + } + //Be sure to update the listen event code block to allow negative damage values through. + } + else if(amt<6) + { + llRegionSayTo(llGetOwnerKey(id),0,"*plink*"); + return; //Blocks micro-LBA, stop that shit + } + else + { + key oid=llGetOwnerKey(id); + integer directional_amt; + if(tmod==ZERO_VECTOR)tmod=collisionmod(pos,targetPos); + directional_amt=llFloor(tmod.x*(float)amt); + if(tmod.y>0.0&&!detrack) + { + if(llFrand(100.0)-amt<0.0)//roll for detrack + { + if(layer>1) + { + llTriggerSound("9213b540-c8de-c7a6-a228-fa3569c5c6ae",1.0); + llOwnerSay("Tracks hit!"); + layer=0; + } + else + { + ++detrack; + list sounds=["af44ee43-b6c8-130a-161d-19282010a84e","d6190a72-9221-3b24-4d0a-a206923f63f1"]; + llTriggerSound(llList2String(sounds,llRound(llFrand(1.0))),1.0); + llOwnerSay("De-tracked!"); + if(!burning)llMessageLinked(-4,0,"",""); + repair=0; + } + } + } + if(tmod.z>0.0&&!burning) + { + if(llFrand(100.0)-amt<0.0)//roll for burn + { + ++burning; + list sounds=["f288bc4f-62bd-9ca1-501e-3afb42d23ef5","2caf350b-ecae-2bc4-1c27-8e7c16ab9e11"]; + llTriggerSound(llList2String(sounds,llRound(llFrand(1.0))),1.0); + llMessageLinked(-4,2,"",""); + repair=0; + } + } + if(directional_amt>1.0) + { + list sounds=["a6c864a1-015a-83d1-bc63-d4b2d5df8482","fd462a07-c691-585c-1c2b-63554c0a71eb","91e2c1a7-238d-b7a7-43b2-00a7fe8f371e"]; + llTriggerSound(llList2String(sounds,llRound(llFrand(2.0))),1.0); + hp-=directional_amt; + } + else //Failed to do damage + { + llOwnerSay("Damage Blocked by Armor"); + llRegionSayTo(llGetOwnerKey(id),0,"Attack was stopped by armor."); + return; + } + llOwnerSay("/me took "+(string)directional_amt+" ("+(string)amt+") damage from "+name+" by "+llKey2Name(oid));//Used to debug output. + llRegionSayTo(oid,0,"/me took "+(string)directional_amt+" ("+(string)amt+") damage"); + } + if(hp<1)die(); + else update(); +} +string modifierstring;//This is visible so moderators can confirm vehicle attributes are within regulation. +update()//SetText +{ + string mod="\n"; + if(burning||detrack) + { + if(burning)mod+="[Burning] "; + if(detrack)mod+="[Detracked]"; + if(!ml)mod+="\n Repair-in-Progress \n"+(string)((integer)repair*10)+"/100"; + } + llSetLinkPrimitiveParamsFast(-4,[PRIM_TEXT,"[LBHD]\n "+(string)hp+" / "+(string)mhp+" HP"+mod,<0.0,0.75,1.0>,1.0, + PRIM_DESC,"LBA.v."+ver+","+(string)hp+","+(string)mhp+","+(string)atcap+",666"+modifierstring]); + //In order: Current HP, Max HP, Max AT accepted, Max healing accepted (Not implemented) +} +die() +{ + llRezObject("Explosion",llGetPos(),ZERO_VECTOR,ZERO_ROTATION,1); + //Add extra shit here + //llResetScript();//Debug + llDie();//Otherwise, use this +} +vector tar(key id) +{ + vector av=(vector)((string)llGetObjectDetails(id,[OBJECT_POS])); + return av; +} +key user; +key gen;//Object rezzer +key me; +integer hear; +boot(integer entry) +{ + modifierstring=",F-"+llGetSubString((string)front,0,2)+//Frontal modifier + ",S-"+llGetSubString((string)side,0,2)+//Side modifier + ",R-"+llGetSubString((string)back,0,2)+//Rear modifier + ",T-"+llGetSubString((string)top,0,2)+//Top modifier + ",B-"+llGetSubString((string)bottom,0,2)+//Bottom modifier + ",M-"+llGetSubString((string)middle,0,2);//Middle Modifier + user=llGetOwner(); + me=llGetKey(); + gen=(string)llGetObjectDetails(me,[OBJECT_REZZER_KEY]); + if(hear)llListenRemove(hear); + integer hex=(integer)("0x" + llGetSubString(llMD5String((string)me,0), 0, 3)); + hear=llListen(hex,"","",""); + llSetTimerEvent(1.0);//Used for auto-delete. + update(); + if(entry)return; + emk=(integer)("0x" + llGetSubString(llMD5String(user,0), 1, 4)); + llListen(emk,"","","emk"); +} +list tracker; +default +{ + state_entry() + { + boot(1); + } + on_rez(integer p) + { + boot(0); + } + listen(integer chan, string name, key id, string message) + { + //[ALWAYS] USE llRegionSayTo(). Do not flood the channel with useless garbage that'll poll every object in listening range. + if(chan==emk) + { + if(llGetOwnerKey(id)!=user)return; + if(detrack) + { + list sounds=["62fafb58-f350-632c-c16d-8928514d52d8","47c80392-832f-8212-a42e-00437fa7ff01"]; + llTriggerSound(llList2String(sounds,llRound(llFrand(1.0))),1.0); + detrack=0; + if(!burning)llMessageLinked(-4,1,"",""); + } + else + { + if(layer<1)++layer; + llOwnerSay("Protected "+(string)layer+" track(s)"); + } + } + else + { + list parse=llParseString2List(message,[","],[" "]); + if(llList2Key(parse,0)==me)//targetcheck + { + list data=llGetObjectDetails(id,[OBJECT_POS,OBJECT_ATTACHED_POINT,OBJECT_ROT,OBJECT_REZZER_KEY]); + vector pos=llGetPos(); + vector targetPos=llList2Vector(data,0); + vector tmod; + integer f=llListFindList(tracker,[name]); + if(f>-1)tmod=llList2Vector(tracker,f+1); + else //Rezzer rezzer's rezzer rezzer + { + f=llListFindList(tracker,[llList2Key(data,4)]); + if(f>-1)tmod=llList2Vector(tracker,f+1); + } + float amt=llList2Float(parse,-1); + if(llFabs(amt)<666.0) + { + if(llList2Integer(data,1)) + { + float dist=llVecDist(targetPos,pos)-1.25;//Backtrack so we don't end up triggering the middle filter. + vector posfix=targetPos+*llList2Rot(data,2);//Do math + if(llVecDist(pos,posfix)<5.0)damage((integer)amt,id,pos,posfix,ZERO_VECTOR,name); + //Check offset to prevent camera-related oofs. + //This technically drops damage but w/e, not a huge issue. + } + else + { + if(tmod)damage((integer)amt,id,pos,targetPos,tmod,name); + else damage((integer)amt,id,pos,targetPos,ZERO_VECTOR,name); + } + } + } + } + } + collision_start(integer c) + { + if(llVecMag(llDetectedVel(0))>40.0) + { + vector gpos=llGetPos(); + if(tracker==[])llSetTimerEvent(1.0); + string name=llDetectedName(0); + integer f=llListFindList(tracker,[name]); + if(f>-1)tracker=llListReplaceList(tracker,[collisionmod(gpos,llDetectedPos(0))],f+1,f+1); + else + { + if(llGetListLength(tracker)>10)tracker=llDeleteSubList(tracker,0,1);//Delete eldest entry to prevent stack-heap + vector cmod=collisionmod(gpos,llDetectedPos(0)); + if(cmod)tracker+=[name,cmod]; + } + //Stores data as follows: OBJECT_NAME,OBJECT_MODIFIER + //Updates objects of the same name to the most recent. + } + } + timer() + { + if(burning||detrack) + { + ml=llGetAgentInfo(user)&AGENT_MOUSELOOK; + if(ml)repair=0; + else if(++repair>9) + { + if(burning) + { + list sounds=["ada6486e-81ef-667b-0a92-17f20184a7eb","fa2f0288-f012-6741-948c-da30f5cfff68","c13344d6-a9b1-3541-5f40-f0703ce97b8d","2a4d1e97-24ec-250b-ac1c-8e2e9134be26","f0fc1dc6-b4b3-f7bf-a3ce-6961845afbad"]; + llTriggerSound(llList2String(sounds,llRound(llFrand(4.0))),1.0); + burning=0; + if(!detrack)llMessageLinked(-4,1,"",""); + llOwnerSay("Fire is out"); + } + else if(detrack) + { + list sounds=["62fafb58-f350-632c-c16d-8928514d52d8","47c80392-832f-8212-a42e-00437fa7ff01"]; + llTriggerSound(llList2String(sounds,llRound(llFrand(1.0))),1.0); + detrack=0; + llMessageLinked(-4,1,"",""); + llOwnerSay("Tracks repaired"); + } + repair=0; + update(); + } + if(burning) + { + hp-=5; + if(hp>0)update(); + else die(); + } + } + if(tar(gen))return; + llDie(); + } +} diff --git a/LBH/README.md b/LBH/README.md new file mode 100644 index 0000000..e7bbc1c --- /dev/null +++ b/LBH/README.md @@ -0,0 +1,29 @@ +[IMPORTANT] + +This requires vehicles/deployables to be aligned properly down the X-axis in order to function properly. Objects which require a rotational offset to function will need to be adjusted. + +Some settings may make the system incompatible with certain rulesets and equipment. However, notes and code for switching these features on and off is present for those who wish to use them. + +Do [not] use LBHD systems as your default LBA parser as it would not be optimized for use in equipment that has no intention of benefitting from directional damage resistances. Use a standard LBA or LBH-Slim/AG core instead. + +[CREDITS] + +Criss Ixtar - For the initial proof of concept and idea, extensive aid with testing and further development. + +Dread Hudson - Establishing the standard LBA format. + +Secondary Lionheart - Method, integration, and code. + +Hadet - For convincing Secondary to make a git for LBHD + +Soapy Boi Gay Pink Dragon - For inspiring the creation of the Hansen, a community effort that has rallied support and development for this project and has allowed us to show off the capabilities of a directional armor system. + +[VERSIONS] + +Slim - Basic Parser, can support Collision Damage. + +AG - Anti-Grief System Included + +HD - Directional Armor, does not support Collision Damage. + +Component - Includes component system diff --git a/LBHD, Directional Armor v1.2.3.lsl b/LBHD, Directional Armor v1.2.3.lsl deleted file mode 100644 index 97d0574..0000000 --- a/LBHD, Directional Armor v1.2.3.lsl +++ /dev/null @@ -1,204 +0,0 @@ -/*[IMPORTANT] This requires vehicles/deployables to be aligned properly down the X-axis in order to function properly. Objects which require a rotational offset to function will need to be adjusted. -The publically issued copy of this code has the following settings disabled: -- Object healing -- Collision Damage -- Line-of-Sight Requirement -- Blocking of micro-LBA. - - -These settings may make the system incompatible with certain rulesets and equipment. However, notes and code for switching these features on and off is present for those who wish to use them. - -Do [not] use this as your default LBA parser as it would not be optimized for use in equipment that has no intention of benefitting from directional damage resistances. Use a standard LBA core or a different LBA parser instead. - -[CREDITS] -datbot Resident/Criss Ixtar - For the initial proof of concept and idea. -Dread Hudson - Establishing the standard LBA format. -Secondary Lionheart - Method and integration - -Note: This should be considered an extention of LBA Slim and possesses limited to no anti-grief. -*/ -integer mhp=100;//Maximum HP -integer hp=mhp;//Current HP -//Positive Numbers Deal Damage -//Negative Numbers Restore Health -//Damage Multipliers: 0 = Invulnerable, 1.0 = 100% Damage, High numbers = Higher Damage -integer atcap=50; -float front=0.5; -float side=1.0; -float back=1.5; -float middle=0.1; -//Note that following modifiers multiply the final damage. So it stacks multiplicatively with the previous modifiers -float top=1.2; -float bottom=1.2; -//Directional Processor -float front_threshold=20.0;//Use positive floats, determines forward range -float back_threshold=160.0;//Use positive floats, determines backward range -float height_threshold=1.5;//How far up/down the Z axis should the source be to registered a top or bottom hit. Should be roughly half the vehicle's height. -integer lbapos(float dmg,vector pos, vector targetPos) -{ - //We'll use numbers greater than -20.0 but less than 20.0 as our forward direction. This means that numbers less -160.0 and greater than 160.0 are our rear. This will need to be changed based on vehicle size and shape. This will not work on Rho because she's too fat. - if(targetPos) - { - float dist=llVecDist(pos,targetPos); - if(dist<1.0)return llFloor(dmg*middle);//This catches explosions which rezzes AT in the object's root position. - else - { - float mod=targetPos.z-pos.z; - if(llFabs(mod)>=height_threshold)//Determines top/bottom hits - { - if(mod>0.0)mod=top;//Top check - else mod=bottom;//Bottom check - } - else mod=1.0;//Else reset it to 1.0 - rotation targetRot=llRotBetween(<1.0,0.0,0.0>*llGetRot(),llVecNorm(-pos)); - vector targetRotVec=llRot2Euler(targetRot)*RAD_TO_DEG; - //You can optimize this further by doing angles in radians as opposed to degrees. This is written in degrees so its easier to read/follow - //For those who care to do so, here's the formulas: [Degrees = (Radians*180.0)/PI] or [Radians = (Degrees*PI)/180.0] - //Degrees should be returned in values between -180.0 and 180.0 - //llSay(0,"Angle: "+(string)trotvec.z+"| Pos offset: "+(string)(tpos-pos)+" | RotBetween: "+(string)trot);//Debug output - //Now we use the Z-Axis to calculate the horizonal directions. - //Note that vertical direction isn't factored, only the horizonal angle. This the vehicle is sliced up like a pie and damage will be based on how far and which direction from the center the projectile strikes when it hits the top or bottom. - if(targetRotVec.z>-front_threshold&&targetRotVec.zback_threshold)//Back - return llFloor((dmg*back)*mod); - else //If it didn't hit any previous angles, the only thing left to hit is the sides. - return llFloor((dmg*side)*mod); - } - } - else return 0;//If a no vector is returned, do not process damage. -} -//Damage Processor -damage(integer amt, key id,vector pos, vector targetPos) -{ - if(amt>atcap)amt=atcap; - /*if(amt<0)//Allows the object to be healed/repaired - { - if(llGetTime()>1.0)//Optional healing cooldown - { - if(amt>(float)hp*0.1)amt=llRound(hp*0.1);//Optional healing cap - hp-=amt; - if(hp>mhp)hp=mhp;//Used to prevent overhealing - llResetTime(); - } - //Be sure to update the listen event code block to allow negative damage values through. - }*/ - /*else if(amt<6)return; //Blocks micro-LBA - else*/ - { - integer directional_amt=lbapos(amt,pos,targetPos); - if(directional_amt)hp-=directional_amt; - else - { - //llRegionSayTo(llGetOwnerKey(id),0,"/me Armor deflected the damage!");//cheeki breeki - return; - } - llOwnerSay("/me took +(string)directional_amt+" ("+(string)amt+") damage");//Used to debug output. - //llRegionSayTo(llGetOwnerKey(id),0,"/me took +(string)directional_amt+" ("+(string)amt+") damage"); - } - if(hp<1)die(); - else update(); -} -//Line-of-Sight Check -integer los(vector start, vector target) -{ - list ray=llCastRay(target,start,[RC_REJECT_TYPES,RC_REJECT_AGENTS,RC_DATA_FLAGS,RC_GET_ROOT_KEY,RC_MAX_HITS,1]); - key hit=llList2Key(ray,0);//Debug - if(llKey2Name(hit)) - { - //llSay(0,llKey2Name(hit));//Debug - if(hit==me)return 1; - else return 0;//Object in way - } - else - { - if(llList2Vector(ray,1)==ZERO_VECTOR)return 1; - else return 0;//Land in way - } -} -string modifierstring;//This is visible so moderators can confirm vehicle attributes are within regulation. -update()//SetText -{ - llSetLinkPrimitiveParamsFast(-4,[PRIM_TEXT,"[LBHD]\n "+(string)hp+" / "+(string)mhp+" HP",<0.0,0.75,1.0>,1.0, - PRIM_DESC,"LBA.v.LBHD,"+(string)hp+","+(string)mhp+","+(string)atcap+",999"+modifierstring]); - //In order: Current HP, Max HP, Max AT accepted, Max healing accepted (Not implemented) -} -die() -{ - //Add extra shit here - //llResetScript();//Debug - llDie();//Otherwise, use this -} -vector tar(key id) -{ - vector av=(vector)((string)llGetObjectDetails(id,[OBJECT_POS])); - return av; -} -key user; -key gen;//Object rezzer -key me; -integer hear; -boot() -{ - modifierstring=",F-"+llGetSubString((string)front,0,2)+//Frontal modifier - ",S-"+llGetSubString((string)side,0,2)+//Side modifier - ",R-"+llGetSubString((string)back,0,2)+//Rear modifier - ",T-"+llGetSubString((string)top,0,2)+//Top modifier - ",B-"+llGetSubString((string)bottom,0,2)+//Bottom modifier - ",M-"+llGetSubString((string)middle,0,2);//Middle Modifier - user=llGetOwner(); - me=llGetKey(); - gen=(string)llGetObjectDetails(me,[OBJECT_REZZER_KEY]); - if(hear)llListenRemove(hear); - integer hex=(integer)("0x" + llGetSubString(llMD5String((string)me,0), 0, 3)); - hear=llListen(hex,"","",""); - llSetTimerEvent(5.0);//Used for auto-delete. - update(); -} -default -{ - state_entry() - { - boot(); - } - on_rez(integer p) - { - if(p>1)//Allows HUD/Objects to set HP value when rezzed with a param, otherwise uses default - { - mhp=p; - hp=p; - } - boot(); - } - listen(integer chan, string name, key id, string message) - { - //[ALWAYS] USE llRegionSayTo(). Do not flood the channel with useless garbage that'll poll every object in listening range. - list parse=llParseString2List(message,[","],[" "]); - if(llList2Key(parse,0)==me)//targetcheck - { - vector pos=llGetPos(); - vector targetPos=tar(id); - //if(los(pos,tpos))//Enforces LBA line-of-sight - { - float amt=llList2Float(parse,-1); - //if(llFabs(amt)<666.0)damage((integer)amt,id,pos,tpos);//Use this code to allow object healing, Blocks overflow attempts - if(amt>0)damage((integer)amt,id,pos,targetPos);//Use this code if you do not wish to support healing - } - //else llRegionSayTo(llGetOwnerKey(id),0,"/me Armor deflected the damage!");//cheeki breeki - } - } - /*collision_start(integer c)//Enable this block if you want to support legacy collisions. - { - if(llVecMag(llDetectedVel(0))>40.0) - { - hp-=c; - if(hp<1)die();//llDie(); - else update(); - } - }*/ - timer()//Auto-deleter. Will kill object if avatar leaves the region or spawning object is removed. - { - if(tar(gen))return; - llDie(); - } -}