Blockland Forums > Modification Help

Playing sound from location of projectile impact?

Pages: (1/3) > >>

Ctrooper:

So im using the SFX system that Package_Complex uses for my weapons and im having trouble implementing sounds played from locations that projectiles land.

Heres the support script:

--- Code: ---function strStart(%str, %search)
{
    return getSubStr(%str, 0, strlen(%search)) $= %search;
}

function strEnd(%str, %search)
{
    %len1 = strlen(%str);
    %len2 = strlen(%search);

    return strlen(%len1) >= strlen(%len2) && getSubStr(%str, %len1 - %len2, %len2) $= %search;
}

function strStartCut(%str, %search)
{
    return getSubStr(%str, strlen(%search), strlen(%str));
}

function strirpos(%str, %search)
{
    %len = strlen(%search);

    for (%i = strlen(%str) - %len; %i >= 0; %i--)
    {
        if (getSubStr(%str, %i, %len) $= %search)
            return %i;
    }

    return -1;
}

function SFXEffect::onAdd(%this)
{
    %name = %this.getName();

    if (%name $= "")
    {
        error("ERROR: SFXEffect objects must have a name!");
        %this.delete();
        return;
    }

    // If this is a duplicate, delete the old one.
    %this.setName("");
    %original = nameToID(%name);
    %this.setName(%name);

    if (%original != -1 && %original.class $= "SFXEffect")
        %original.delete();

    // Go through fields to discover all layers
    // We'll have to use local variables for everything because this looks
    // through the fields of %this, and we don't want to mess it up.
    for (%i = 0; 1; %i++)
    {
        %tag = %this.getTaggedField(%i);

        if (%tag $= "")
            break;

        %field = getField(%tag, 0);
        %value = getFields(%tag, 1, getFieldCount(%tag));

        // This part is really repetitive because we can't use fields here
        // Sorry! :P
        // Technically it could be cleaned up with globals but that's a whole
        // other can of worms
        if (strStart(%field, "file"))
        {
            %field = strStartCut(%field, "file");
            %index = strirpos(%field, "_");

            if (%index != -1)
            {
                %handle = getSubStr(%field, %index + 1, strlen(%field));
                %field = getSubStr(%field, 0, %index);
            }
            else
                %handle = "";

            if (!%isLayer[%field])
            {
                %isLayer[%field] = true;
                %layer[%maxLayer++] = %field;
            }

            %sample[%field, %maxSample[%field]++] = %handle;
        }
        else if (strStart(%field, "description"))
        {
            %field = strStartCut(%field, "description");
            %index = strirpos(%field, "_");

            if (%index != -1)
            {
                %handle = getSubStr(%field, %index + 1, strlen(%field));
                %field = getSubStr(%field, 0, %index);
            }

            if (!%isLayer[%field])
            {
                %isLayer[%field] = true;
                %layer[%maxLayer++] = %field;
            }

            %sample[%field, %maxSample[%field]++] = %handle;
        }
        else if (strStart(%field, "profile"))
        {
            %field = strStartCut(%field, "profile");
            %index = strirpos(%field, "_");

            if (%index != -1)
            {
                %handle = getSubStr(%field, %index + 1, strlen(%field));
                %field = getSubStr(%field, 0, %index);
            }

            if (!%isLayer[%field])
            {
                %isLayer[%field] = true;
                %layer[%maxLayer++] = %field;
            }

            %sample[%field, %maxSample[%field]++] = %handle;
        }
        // Now that I think about it, maybe globals would be better...
        // else if (strStart(%field, "useSource2D"))
        // {
        //     %field = strStartCut(%field, "useSource2D");
        //
        //     if (!%isLayer[%field])
        //     {
        //         %isLayer[%field] = true;
        //         %layer[%maxLayer++] = %field;
        //     }
        // }
        // else if (strStart(%field, "distanceThreshold"))
        // {
        //     %field = strStartCut(%field, "distanceThreshold");
        //
        //     if (!%isLayer[%field])
        //     {
        //         %isLayer[%field] = true;
        //         %layer[%maxLayer++] = %field;
        //     }
        // }
    }

    // Thank god that's over, now we can start making a mess with fields!
    %this.layerCount = 0;

    for (%layerIndex = 1; %layerIndex <= %maxLayer; %layerIndex++)
    {
        %layerName = %layer[%layerIndex];
        %layerMaxSample = %maxSample[%layerName];

        if (%layerMaxSample < 1)
        {
            // TODO: Do this after trying to load samples so that invalid samples don't count
            warn("SFXEffect " @ %name @ " has no samples on layer " @ %layerName @ ", ignoring layer...");
            continue;
        }

        %this.layerName[%this.layerCount] = %layerName;
        %this.layerCount++;
        %this.sampleCount[%layerName] = 0;

        for (%sampleIndex = 1; %sampleIndex <= %layerMaxSample; %sampleIndex++)
        {
            %sampleName = %sample[%layerName, %sampleIndex];

            if (%this.profile[%layerName, %sampleName] $= "")
            {
                if (%this.file[%layerName, %sampleName] $= "")
                {
                    warn("SFXEffect " @ %name @ " has no file or profile for sample " @ %sampleName @ " on layer " @ %layerName @ ", ignoring sample...");
                    continue;
                }

                %fileName = %this.file[%layerName, %sampleName];
                %description = FireSFX3d;
                %preload = true;

                if (%this.description[%layerName, %sampleName] !$= "")
                    %description = %this.description[%layerName, %sampleName];

                // Should probably getSafeVariableName the %name
                %profileName = "__SFXEffect_AudioProfile_" @ %name @ "_" @ getSafeVariableName(%layerName) @ "_" @ getSafeVariableName(%sampleName);
                %profile = nameToID(%profileName);

                if (!isObject(%profile))
                {
                    %profileName = "__SFXEffect_AudioProfile_" @ getSafeVariableName(%fileName) @ "_" @ getSafeVariableName(%description.getName());
                    echo("making " @ %profileName);
                    eval("datablock AudioProfile(" @ %profileName @ "){fileName=%fileName;description=%description;preload=%preload;};");
                    %profile = nameToID(%profileName);
                }

                if (!isObject(%profile))
                {
                    warn("SFXEffect " @ %name @ " failed to create profile for sample " @ %sampleName @ " on layer " @ %layerName @ ", ignoring sample...");
                    continue;
                }

                %this.profile[%layerName, %sampleName] = %profile;
            }

            %this.sampleHandle[%layerName, %this.sampleCount[%layerName]] = %sampleName;
            %this.sampleCount[%layerName]++;
        }
    }
}

function SFXEffect::playTo(%this, %client, %position, %source)
{
    %control = %client.getControlObject();

    if (!isObject(%control))
    {
        %client.debugSFX(%this, "not playing: no control object");
        return;
    }

    %isSource = %client == %source;
    %distance = vectorDist(%position, %control.getPosition());

    for (%i = 0; %i < %this.layerCount; %i++)
    {
        %layerName = %this.layerName[%i];

        if (%this.sampleCount[%layerName] < 1)
        {
            %client.debugSFX(%this, "not playing " @ %layerName @ ": no samples");
            continue;
        }

        switch$ (%this.filterListener[%layerName])
        {
            case "source": if (!%isSource) { %client.debugSFX(%this, "not playing " @ %layerName @ ": filterListener"); continue; }
            case "other": if (%isSource) { %client.debugSFX(%this, "not playing " @ %layerName @ ": filterListener"); continue; }
        }

        if (%this.filterDistanceMin[%layerName] !$= "" && %distance < %this.filterDistanceMin[%layerName])
        {
            %client.debugSFX(%this, "not playing " @ %layerName @ ": filterDistanceMin" SPC %distance);
            continue;
        }

        if (%this.filterDistanceMax[%layerName] !$= "" && %distance > %this.filterDistanceMax[%layerName])
        {
            %client.debugSFX(%this, "not playing " @ %layerName @ ": filterDistanceMax" SPC %distance);
            continue;
        }

        %use2D = false;

        switch$ (%this.use2D[%layerName])
        {
            case "always" or "1": %use2D = true;
            case "source": %use2D = %isSource;
            case "other": %use2D = !%isSource;
            default: %use2D = false;
        }

        %sampleIndex = getRandom(%this.sampleCount[%layerName] - 1);
        %sampleHandle = %this.sampleHandle[%layerName, %sampleIndex];

        %profile = %this.profile[%layerName, %sampleHandle];

        if (!isObject(%profile))
        {
            %client.debugSFX(%this, "not playing " @ %layerName @ ": invalid sample " @ %sampleHAndle);
            continue;
        }

        %client.debugSFX(%this, "playing " @ %layerName @ ": " @ %use2D SPC %sampleHandle);

        if (%use2D)
            %client.play2D(%profile);
        else
            %client.play3D(%profile, %position);
    }
}

function SFXEffect::play(%this, %position, %source)
{
    %count = ClientGroup.getCount();

    for (%i = 0; %i < %count; %i++)
        %this.playTo(ClientGroup.getObject(%i), %position, %source);
}

function SFXEffect::playFrom(%this, %position, %object)
{
    if (!isFunction(%object.getClassName(), "getControllingClient"))
        return %this.play(%position, 0);

    return %this.play(%position, %object.getControllingClient());
}

function GameConnection::debugSFX(%this, %sfx, %text)
{
    if (%this.debugSFX || %this.debugSFX[%sfx.getName()])
        messageClient(%this, '', "\c4debugSFX (" @ %sfx.getName() @ ")\c6: " @ %text);
}

--- End code ---

and using this guy

--- Code: ---FireSFX.playFrom(%obj.getMuzzlePoint(%slot), %obj);
--- End code ---
I can play a set of audio from the position "MuzzlePoint"

Now i want to be able to play the SFX when a projectile explodes or collides with the ground but im not sure how to write it out so it gets the location of the projectile and plays the SFX from there.

The HE grenade in Package_Complex does this

--- Code: ---HEGrenadeExplodeSFX.playFrom(%position, %object);
--- End code ---

but ive tried this with my weapons plus other variations (which is basically just me plopping random variables) and ive gotten no luck.
Can someone show me how to set this up or tell me what im doing wrong?

This is what i have for the projectile that im using

--- Code: ---function SMAWProjectile::onCollision(%this, %slot)
{
ATExplosionSFX.playFrom(%this.getPosition(%slot), %this);
}
--- End code ---


phflack:

HE grenade does

--- Code: ---function hegrenadeProjectile::onCollision(%this,%obj,%col,%fade,%pos,%normal)
{
serverPlay3D(hegrenadeBounceSound,%obj.getTransform());
}

--- End code ---

maybe copy that?

Ctrooper:

Thats what i was using before but i want to play this

--- Code: ---new ScriptObject(ATExplosionSFX)
{
class = "SFXEffect";

    file["close", 1] = "Add-Ons/Weapon_ATWeapons/Explosion/ATClose1.wav";
    file["close", 2] = "Add-Ons/Weapon_ATWeapons/Explosion/ATClose2.wav";
    file["close", 3] = "Add-Ons/Weapon_ATWeapons/Explosion/ATClose3.wav";
    filterDistanceMax["close"] = 100;
    use3D["close"] = "source";

    file["far", 1] = "Add-Ons/Weapon_ATWeapons/Explosion/ATMid1.wav";
    file["far", 2] = "Add-Ons/Weapon_ATWeapons/Explosion/ATMid2.wav";
    file["far", 3] = "Add-Ons/Weapon_ATWeapons/Explosion/ATMid3.wav";
    filterDistanceMin["far"] = 100;
filterDistanceMax["far"] = 300;
    use3D["far"] = "always";

file["very_far", 1] = "Add-Ons/Weapon_ATWeapons/Explosion/ATFar1.wav";
file["very_far", 2] = "Add-Ons/Weapon_ATWeapons/Explosion/ATFar2.wav";
file["very_far", 3] = "Add-Ons/Weapon_ATWeapons/Explosion/ATFar3.wav";
    filterDistanceMin["very_far"] = 300;
filterDistanceMax["very_far"] = 2000;
    use3D["very_far"] = "always";
};
--- End code ---
When the projectile impacts which requires me to use something similiar to this in the onCollide function

--- Code: ---FireSFX.playFrom(%obj.getMuzzlePoint(%slot), %obj);
--- End code ---
i just dont know how to word the line of code so those sounds play aat that position... Feel me? Im not sure how to explain it.

Tendon:

ahm not sure what you want, but If I were trying to play a sound from where the projectile hits something, I would use the results of a trace like this to figure it out.


--- Code: (console.log) ---Leaving [sportBallsPackage]Armor::onTrigger() - return 909
Entering [c4]ProjectileData::onCollision(907, 16663, 11073, 1, 6.387541 46.184765 0.000000, 0.000000 0.000000 1.000000)
   Entering ProjectileData::onCollision(907, 16663, 11073, 1, 6.387541 46.184765 0.000000, 0.000000 0.000000 1.000000)
      Entering getBL_IDFromObject(16663)
         Entering getBrickGroupFromObject(16663)
         Leaving getBrickGroupFromObject() - return 11084
      Leaving getBL_IDFromObject() - return 999999
   Leaving ProjectileData::onCollision() - return 1
Leaving [c4]ProjectileData::onCollision() - return
Entering ProjectileData::onExplode(907, 16663, 6.387541 46.184765 0.010000)
   Entering getBL_IDFromObject(16663)
      Entering getBrickGroupFromObject(16663)
      Leaving getBrickGroupFromObject() - return 11084
   Leaving getBL_IDFromObject() - return 999999
Leaving ProjectileData::onExplode() - return 0
--- End code ---

And then i found the gun projectile here:

--- Code: (server.cs line 218) ---datablock ProjectileData(gunProjectile)
{
   projectileShapeName = "./bullet.dts";
   directDamage        = 30;
--- End code ---

So I'd do something like:

--- Code: (birds.cs) ---deactivatepackage(gunsoundpackage);
package gunsoundpackage
{
   function gunProjectile::onCollision(%data,%proj,%a,%pos,%vec)
   {
      ATExplosionSFX.playFrom(%pos,%proj.sourceobj);
      Parent::onCollision(%data,%proj,%a,%pos,%vec);
   }
};
activatepackage(gunsoundpackage);
--- End code ---

... not sure if %proj.sourceobj is the right field for the person who fired the bullet, but whatever.

Ctrooper:

So im basically trying to get the SFX script that Weapon_Package_Complex uses to work with projectiles exploding. I got it to work with weapons being fired but not for projectiles colliding.

--- Code: ---package gunsoundpackage
{
   function gunProjectile::onCollision(%data,%proj,%a,%pos,%vec)
   {
      ATExplosionSFX.playFrom(%pos,%proj.sourceobj);
      Parent::onCollision(%data,%proj,%a,%pos,%vec);
   }
};
activatepackage(gunsoundpackage);
--- End code ---
Also does this have to be a package?

Pages: (1/3) > >>

Go to full version