Aller au contenu

Photo

Exploding Barrels System


  • Veuillez vous connecter pour répondre
20 réponses à ce sujet

#1
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
 So I am trying to make working barrels that you can blow up if you use fire or a gun (I use blackpowder guns in my module) 

So far I was happy with the one I had made at first, but then I noticed it just won't damage anything with the normal fireball spells, so I try to make a new system... unsuccessfully.

Any help is appreciated (again, lol... I've lots of time and problems.)

#2
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
void ExplodeAtLocation(location lTarget, int nDamage, int nSaveDC = 30, float fRadius = 7.)
{
int nDamageAfterSave = GetReflexAdjustedDamage(nDamage, oObject, nSaveDC);
object oObject = GetFirstObjectInShape(SHAPE_SPHERE, fRadius, lTarget, FALSE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR);
oObject = GetNextObjectInShape(SHAPE_SPHERE, fRadius, lTarget, FALSE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR);
ApplyEffectToObject( DURATION_TYPE_INSTANT, EffectDamage(nDamageAfterSave, DAMAGE_TYPE_FIRE), oObject);

}
//
void main()
{
location lSource = GetLocation(OBJECT_SELF);
object oPC = GetLastHostileActor;
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oPC);

if ((GetDamageDealtByType(DAMAGE_TYPE_FIRE)))
{
DelayCommand(0.1, ExplodeAtLocation(lSource, d20(6)));
PlaySound("zep_explosion");

}

else if ((GetStringLeft(GetResRef(oWeapon), 4)== "gun_"))
{
DelayCommand(0.1, ExplodeAtLocation(lSource, d20(6)));
PlaySound("zep_explosion");
}
else SendMessageToPC(oPC, "You must use fire or a gun");
return;
}

#3
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
That's all I've come up with, and surprisingly it doesn't work... I've tried doing ifs and whiles and dos... but I have no real idea how they work so... well. Help me :D

#4
The Amethyst Dragon

The Amethyst Dragon
  • Members
  • 1 878 messages
This may help...

void ExplodeAtLocation(location lTarget, int nDamage)
{
int nDamageAfterSave;
// get the first object in the area of effect
object oObject = GetFirstObjectInShape(SHAPE_SPHERE, 7.0, lTarget, FALSE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR);
while (oObject != OBJECT_INVALID)  // if oObject is not invalid, try to damage it!
   {
   // Each target object makes it's own Reflex save against the original damage (nDamage)
   nDamageAfterSave = GetReflexAdjustedDamage(nDamage, oObject, 30, SAVING_THROW_TYPE_FIRE);
   if (nDamageAfterSave > 0)    // if target object should suffer any damage, apply it and a fire VFX
      {
      ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDamageAfterSave, DAMAGE_TYPE_FIRE), oObject);
      ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_FLAME_M), oObject);
      }
   // get the next object in the area of effect
   oObject = GetNextObjectInShape(SHAPE_SPHERE, 7.0, lTarget, FALSE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR);
   }
}

//  On Damaged script for exploding barrel object

void main()
{
location lSource = GetLocation(OBJECT_SELF);
object oPC = GetLastHostileActor();
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oPC);

if (GetDamageDealtByType(DAMAGE_TYPE_FIRE) > 0)
   {
   DelayCommand(0.1, ExplodeAtLocation(lSource, d20(6)));
   PlaySound("zep_explosion");
   }
else if (GetStringLeft(GetResRef(oWeapon), 4) == "gun_")
   {
   DelayCommand(0.1, ExplodeAtLocation(lSource, d20(6)));
   PlaySound("zep_explosion");
   }
else
   {
   SendMessageToPC(oPC, "You must use fire or a gun");
   }
}

Modifié par The Amethyst Dragon, 12 août 2013 - 08:02 .


#5
The Amethyst Dragon

The Amethyst Dragon
  • Members
  • 1 878 messages
The script above made some basic changes to yours.

I put the save DC and explosion radius right into the ExplodeAtLocation() function, since it's just for this script right now and doesn't need to be changed.

I added a proper while loop to the explosion so it cycles through the objects in the area of effect. The reflex save is now done by each object in the area of effect, rather than being done at the start and adjusting damage for every creature after the first.

I added a few comments to the code so you can see what some of the parts of it are supposed to be doing.

You might want to consider changing the delay in exploding from 0.1 seconds to something a little longer, perhaps to 1.0 or even 2.0 seconds, just for effect.

If you have this as the on damaged script for your barrels, it should work.  And if you line several of these up within 7 meters of the last one, you could get a chain of explosions as the first sets off the second, and that sets off the third, and onward...

:devil:

Modifié par The Amethyst Dragon, 12 août 2013 - 08:15 .


#6
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
Thanks. :) Now I need to try and understand how I will go about adding that damage. As far as I can see it's already supposed to be there... right ? O_o or am I just blind

#7
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
= Tested and it doesn't do a thing, just plays the explosion sound :D Am I being dumb here ? lol

#8
Fester Pot

Fester Pot
  • Members
  • 1 394 messages
Is the static box unchecked for all your barrels?

FP!

#9
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
Yeah, their point is to be useable and portable. I can lug them around and set them back beside myself and now I'm trying to blow them up. I'm just curious though...

ExplodeAtLocation(lSource, d20(6)));

Isn't that the damage dealing thingie ? If so, then the lSource is missing ?

Seriously, talk the grunting orc language to me, I'm not even novice at this yet x)

Modifié par JerrodAmolyan, 12 août 2013 - 08:32 .


#10
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
Okay, got the damage and effects applied myself. NOW... I'd like to make it a bit less... well predictable. I had to assign it 100 damage, since it doesn't seem to recognize any d100 or 10d20 or anything with dice. Or if it would, I don't know the correct type :P And the visual doesn't apply to the adjacent barrels, only the one I shoot at :(

Also, I'd like to make it blow up the PC (if he gets in the radius and miraculously even evades the fire) if he carries those barrels ("jer_explosives") and make those barrels then be taken from the inventory :P How can I do that ?

Modifié par JerrodAmolyan, 12 août 2013 - 08:50 .


#11
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
I've still been unable to work this out. Seems I can't blow up the adjacent barrels, instead the damage just either destroys them, or if I give them lots of hit points, does nothing to them.

Also, I'm unable to assign a damage like 10d20 (or anything d anything) I can just assign a number which will be it, meh. Not that 100 damage isn't "enough", it's just so predictable and you can't get lucky and evade some of it by rolling well. if you fail the reflex, it's 100 damage. It gets boring :P

Biggest problem is not getting the barrels explode if hit by another barrel, I think it might have something to do with PC being the one who triggers the event, but the barrel being the one who causes the damage... then again it's just a hunch. I really need help :)

#12
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
You need to post your current code for us to help with it. :)

Funky

#13
HipMaestro

HipMaestro
  • Members
  • 1 515 messages
Scripting dunce here... but try changing the radius of the GetFirstObjectInShape to a constant like RADIUS_SIZE_HUGE and retry. The effect may not be locating target(s) properly.  Have you tried different spacings of the barrels?  (The others may be lying just outside the edge of the radius.)  

*bumping until a pro shows*

#14
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
*Derps* Right the current code !

void ExplodeAtLocation(location lTarget, int nDamage)

{int nDamageAfterSave;
// get the first object in the area of effect
object oObject = GetFirstObjectInShape(SHAPE_SPHERE, 7.0, lTarget, FALSE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR);
while (oObject != OBJECT_INVALID)  // if oObject is not invalid, try to damage it! 
 {   // Each target object makes it's own Reflex save against the original damage (nDamage)   
nDamageAfterSave = GetReflexAdjustedDamage(nDamage, oObject, 30, SAVING_THROW_TYPE_FIRE);   
if (nDamageAfterSave > 0)  
 // if target object should suffer any damage, apply it and a fire VFX     
{      ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(100, nDamageAfterSave, DAMAGE_TYPE_FIRE), oObject);     
ActionCastSpellAtObject(SPELL_COMBUST, oObject, METAMAGIC_ANY, TRUE, 0,
PROJECTILE_PATH_TYPE_DEFAULT, TRUE);     
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_FLAME_M), oObject);      ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_FIREBALL), lTarget);
      }
   // get the next object in the area of effect   oObject = GetNextObjectInShape(SHAPE_SPHERE, 7.0, lTarget, FALSE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR); 
 }
}
//  On Damaged script for exploding barrel object
void main()
{location lSource = GetLocation(OBJECT_SELF);
object oPC = GetLastHostileActor();
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oPC);

if (GetDamageDealtByType(DAMAGE_TYPE_FIRE) > 0) 
 {   DelayCommand(0.1, ExplodeAtLocation(lSource, d20(6))); 
 PlaySound("zep_explosion");   
}
else if (GetStringLeft(GetResRef(oWeapon), 4) == "gun_") 
 {   DelayCommand(0.1, ExplodeAtLocation(lSource, d20(6)));   
PlaySound("zep_explosion");   
}
else 
 {   
SendMessageToPC(oPC, "You must use fire or a gun");   
}
}

Modifié par JerrodAmolyan, 14 août 2013 - 08:40 .


#15
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
There are numerous problems in your script. You have the parameters for EffectDamage wrong, and you commented out the line that continues to iterate the while loop. You also appear to be having it cast a Combust spell for no reason I can fathom. I'll post a cleaned-up version in a couple minutes.

Funky

#16
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
Sorry, I got sidetracked chatting. Here's a test mod with it working:
Barrels Go Boom

Here's the cleaned up script, though I suggest you just yank the one from the mod if the forum eats the indents:

void ExplodeAtLocation(location lTarget) {
    int nDamage;
    ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_FIREBALL), lTarget);

    object oObject = GetFirstObjectInShape(SHAPE_SPHERE, 7.0, lTarget, FALSE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR);
    while (GetIsObjectValid(oObject)) {

        nDamage = GetReflexAdjustedDamage(d20(6), oObject, 30, SAVING_THROW_TYPE_FIRE);

        if (nDamage > 0) {
            ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDamage, DAMAGE_TYPE_FIRE), oObject);
            ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_FLAME_M), oObject);
        }

        oObject = GetNextObjectInShape(SHAPE_SPHERE, 7.0, lTarget, FALSE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR);
    }
}

void main() {

    location lSource = GetLocation(OBJECT_SELF);
    object oPC = GetLastHostileActor();
    object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oPC);

    if (GetDamageDealtByType(DAMAGE_TYPE_FIRE) > 0) {

        DelayCommand(0.1, ExplodeAtLocation(lSource));
        PlaySound("zep_explosion");

    } else if (GetStringLeft(GetResRef(oWeapon), 4) == "gun_") {

        DelayCommand(0.1, ExplodeAtLocation(lSource));
        PlaySound("zep_explosion");
    }
    else {
        SendMessageToPC(oPC, "You must use fire or a gun to detonate this barrel.");
    }
}


I would probably have written it a bit differently (I just cleaned up your version), but it works as expected.

Funky

#17
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
Hey thanks, this script is just what I wanted. :) The module one is very complicated, and I just want a simple exploding barrel you can lug around and so. Of course, I'd like to ask if it's possible for me to add an if sentence somewhere to check if the PC has this barrel in his/her inventory, and if so and caught in that sphere, the PC would also explode = death and losing the barrels. Where would this sentence go to ? To the explosion script or to the main script ?

#18
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
The test module one is identical to the one I posted. Just download it, open it in the editor, and hit F9 to test (assuming your test toon has fire damage). Otherwise, just play it - only takes a minute, and shows off the domino effect.

Where you put the line checking for a barrel in inventory depends on what behavior you want, what you expect the use by players to be, and so on. If you only care about barrels in inventory of the person who sets off the first barrel, you can avoid putting it in the explosion function. If you do care about secondary explosions setting off barrels in player inventory, however, it will have to go in the explosion function, inside the while loop.

You'd need another custom function to iterate the pc's inventory, delete all instances of the barrel while counting deleted instances, and return the number of deleted instances, to know how much damage to apply. Here's a modified script that checks inside the explosion:


int DeleteCountItem(object oPC, string sTag) {
    int nCount;
    object oScan = GetFirstItemInInventory(oPC);
    while (GetIsObjectValid(oScan)) {
        if (GetTag(oScan) == sTag) {
            nCount++;
            DestroyObject(oScan);
        }
        oScan = GetNextItemInInventory(oPC);
    }
    return nCount;
}

void ExplodeAtLocation(location lTarget) {
    int nDamage, nCount;
    ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_FIREBALL), lTarget);

    object oObject = GetFirstObjectInShape(SHAPE_SPHERE, 7.0, lTarget, FALSE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR);
    while (GetIsObjectValid(oObject)) {

        if (GetIsPC(oObject)) //saves us from scanning inventory of placeables and other creatures
            nCount = DeleteCountItem(oPC, "TAGOFYOURITEM");


        nDamage = GetReflexAdjustedDamage(d20(6*(nCount+1)), oObject, 30, SAVING_THROW_TYPE_FIRE);

        if (nDamage > 0) {
            ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDamage, DAMAGE_TYPE_FIRE), oObject);
            ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_FLAME_M), oObject);
        }

        oObject = GetNextObjectInShape(SHAPE_SPHERE, 7.0, lTarget, FALSE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR);
    }
}

void main() {

    location lSource = GetLocation(OBJECT_SELF);
    object oPC = GetLastHostileActor();
    object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oPC);

    if (GetDamageDealtByType(DAMAGE_TYPE_FIRE) > 0) {

        DelayCommand(0.1, ExplodeAtLocation(lSource));
        PlaySound("zep_explosion");

    } else if (GetStringLeft(GetResRef(oWeapon), 4) == "gun_") {

        DelayCommand(0.1, ExplodeAtLocation(lSource));
        PlaySound("zep_explosion");
    }
    else {
        SendMessageToPC(oPC, "You must use fire or a gun to detonate this barrel.");
    }
}

Fair warning: I haven't compiled this, so there could be a typo.

Funky

#19
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
You forgot to assign PC as object, but it's okay. The problem still is that the barrels won't get destroyed from your inventory, strangely enough. I'm sure the tag of the item is correct.

Otherwise it works, it does assign damage and blow you up (needed to apply fireball visual to the item holding PC too but yeah. Thanks alot for helping me here :)

Modifié par JerrodAmolyan, 15 août 2013 - 07:36 .


#20
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages

JerrodAmolyan wrote...

You forgot to assign PC as object, but it's okay. The problem still is that the barrels won't get destroyed from your inventory, strangely enough. I'm sure the tag of the item is correct.


No, it's not okay. That's WHY the barrels aren't being taken. :P

Change that line's oPC to oObject, like this:
nCount = DeleteCountItem(oObject, "TAGOFYOURITEM");
Funky

#21
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
AAAAH. Damn, now it seems to work flawlessly :P Thanks man.