Jump to content
The Dark Mod Forums

Weapon Projectile issue


acdcbelmar

Recommended Posts

Hi, i start with a new fan mission but i get a problem, when i shot with a custom weapon that launch a lot of projectiles with a lot of spread,(like a shotgun) the projectile spread don't work, all projectiles are launched in to the same place (center view), it's very frustrating, maybe its a code bug, but in the weapon script "launchprojectiles();" the spread and the num_projectiles are not working.

Please, if anyone knows how i can fix it, just leave a reply or any information about that. If someone works on the official code, maybe can fix that issue for the new release, that can be useful for people that wants improve the actual weapons.

Sorry for my basic english, my mother language is spanish :)

Link to comment
Share on other sites

The weapon is a double barrel gun, in the fire function, here is the script


void weapon_arrowz::Fire() 
{  float ammoClip;
    ammoClip = ammoInClip();
    entity playerOwn = getOwner();
    if ( ammoClip == 1 ) {
        playAnim( ANIMCHANNEL_ALL, "fire_last" );
    }
    if ( ammoClip > 1 ) {
        playAnim( ANIMCHANNEL_ALL, "fire" );
    }
    launchProjectiles( 8, 8, 0, 1.0, 1.0 );            //here is the problem
    launchProjectiles( 12, 16, 0, 1.0, 1.0 );       // the spread is not working, first value "num of projectiles", second value "spread"

    waitUntil( animDone( ANIMCHANNEL_ALL, ARROWZ_FIRE_TO_IDLEX ) );
    weaponState( "Idle", ARROWZ_FIRE_TO_IDLEX );
}

i can post the full script of the weapon, but the problem is the launchprojectiles function,  but here is it

 

tdm_weapon_arrowz.script

Edited by acdcbelmar
more especifications
Link to comment
Share on other sites

handgun works fine because uses iron sights, melee weapons are using the normal collision melee system, i want put a crossbow that can launch 3 arrows (enemies also can use the weapon, but for now only professional thieves can use the handgun ), in this mission the weapons are droppable, so you can clear your inventory of weak weapons. I think that add a weight for each special item can solve the unlimited inventory, so more items, more slow movement. what do you think?

spcleaning_2019-08-11_17.58.46.jpg

spcleaning_2019-08-11_17.58.50.jpg

spcleaning_2019-08-11_18.02.23.jpg

spcleaning_2019-08-11_18.02.42.jpg

Link to comment
Share on other sites

The mission is about slave traffic(horror), you must run away from your captors and decide if save the another persons. I have some monsters for the nightmare zones ( are zones in that the fear of the people manifests as monsters). I am learning how to use the darkradiant, because i was use the d3editor a lot of time, this summer i will release the mission i think, but the only thing that a want fix is the problem of the projectiles, the shotgun script and sound are very good, the model can change.

In the weapon projectile i was test the "firealongplayerview" and "launchfrombarrel" keys, but they not fix the problem

Edited by acdcbelmar
more especifications
Link to comment
Share on other sites

Here is the relevant code:

float spreadRad = DEG2RAD( spread );
for( i = 0; i < num_projectiles; i++ ) {
    ang = idMath::Sin( spreadRad * gameLocal.random.RandomFloat() );
    spin = (float)DEG2RAD( 360.0f ) * gameLocal.random.RandomFloat();
    //dir = playerViewAxis[ 0 ] + playerViewAxis[ 2 ] * ( ang * idMath::Sin( spin ) ) - playerViewAxis[ 1 ] * ( ang * idMath::Cos( spin ) );
    dir = muzzleAxis[ 0 ]; // Dram: Make the weapon shoot directly from the barrel bone. Found by Ishtvan
    if (projectileDef->dict.GetBool("fire_along_playerview", "0")) {
        // greebo: Fire the projectile along the playerview direction
        dir = playerViewAxis.ToAngles().ToForward();
    }

The corresponding commit:

Revision: 1417
Author: dram
Date: 10 октября 2007 г. 13:08:24
Message:
-Changed weapon and player so that the arrow is launched from the muzzle angle rather then the player angle
-Changed the drifting to use 3 fracsins so that each axis is irrelevant of the other, thus giving a more random drifting
----
Modified : /trunk/game/player.cpp
Modified : /trunk/game/weapon.cpp

I think the original intent was to change the shooting direction from "view" to "muzzle". The spread was removed in process. The option to shoot by "view" direction was later returned under fire_along_playerview arg.

It seems that we can restore the spread back, but there are two problems:

  1. If some existing weapons accidentally pass nonzero spread, we will have to fix them too.
  2. If we fix the code, it would be hard for you to use it right now. Although I guess it is not impossible: we can build executable at current SVN, and give you folder with current shaders to override the ones from 2.07.
Link to comment
Share on other sites

Thanks for the reply. I understand the situation and i think that i can wait for the code fix, i was try to build the 2.06 version and i was fix the problem, but 2.06 get me a lot of crashes, so like i said, i can wait for that. Here is the that i was added, maybe can help:

//////////////////////////////////////////////////////////////////////////////////////////////////////////// thanks ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

This is other thing, it's not essential but i notice that when i test some functions

Another thing i had noticed is when you drop a item from the inventory that uses "inventoryDrop();" script (a custom player tool for example) the item is not dropped, the script runs but the item persist in the inventory, here is the code: this script is for use a item(playertool) for select a weapon like a inventory item, using "tdm_frob_weapon_selects_weapon" because the script that i made gives you a item, and if that is a weapon, you automatically select that item, so i can limit the amount of weapons, this is for my FM.

object playertools_weapon_knifeb : player_tools {
    string weapon;
    string item;
    void inventoryUse(entity userEntity, entity frobbedEntity, float buttonState);
    void inventoryDrop();   // here is it the other thing, the script runs but the item is not dropped
};
void playertools_weapon_knifeb::inventoryUse(entity userEntity, entity frobbedEntity, float buttonState)
{
     entity knifeb = sys.spawn(getKey("def_weapon_select"));
         $player1.addInvItem(knifeb);
}
void playertools_weapon_knifeb::inventoryDrop()
{
    weapon=getKey("def_weapon_select");
    item=getKey("def_item_drop");
    if ( $player1.getCurrentWeapon() == getKey("def_weapon_select"))
        {    
    entity knifey = sys.spawn("atdm:weapon_unarmed_item");
           $player1.addInvItem(knifey);
    $player1.selectWeapon("atdm:weapon_unarmed");
    }

$player1.changeInvItemCount(getKey("inv_name"), getKey("inv_category"), -1); // for some reason, this function dont work, i cant understand why

/* // here is my script fix, but is better have a code function for this, 

  $player1.replaceInvItem(getCurInvItemEntity(),$null_entity);

    entity projectiles = sys.spawn(getKey("def_item_drop"));
    vector viewAngless = $player1.getViewAngles();
    vector directions = sys.angToForward(viewAngless);
    vector velocitys = directions;
    vector origins = $player1.getEyePos();
    origins += directions * 30;
    projectiles.setOrigin(origins);

*/

}

/*ANOTHER FORM FOR THE TOOL DROP CODE*/


object playertools_weapon_shortsword : player_tools {
    void inventoryUse(entity userEntity, entity frobbedEntity, float buttonState);
    void inventoryDrop();
};
void playertools_weapon_shortsword::inventoryUse(entity userEntity, entity frobbedEntity, float buttonState)
{
     entity knife = sys.spawn("atdm:weapon_shortsword");
         $player1.addInvItem(knife);
}
void playertools_weapon_shortsword::inventoryDrop()
{
    if ( $player1.getCurrentWeapon() == "atdm:weapon_shortsword")
        {    
    entity knifex = sys.spawn("atdm:weapon_unarmed_item"); // custom item for select the unarmed weapon, using tdm_frob_weapon_select_weapon that selects the weapon that you pickup
           $player1.addInvItem(knifex);
    $player1.selectWeapon("atdm:weapon_unarmed");
    }
    $player1.replaceInvItem(getCurInvItemEntity(),$null_entity);

    entity projectile = sys.spawn("atdm:playertools_weapon_knife");
    vector viewAngles = $player1.getViewAngles();
    vector direction = sys.angToForward(viewAngles);
    vector velocity = direction;
    vector origin = $player1.getEyePos();
    origin += direction * 30;
    projectile.setOrigin(origin);
//    holdEntity(projectile.getName());


}

/////////////////////////////////////////////// for this thing maybe the problem is in the player.cpp , in this part of the code ///////////////////////////////////////////////////////

void idPlayer::DropInventoryItem()
{
    bool bDropped = false;
    CGrabber *grabber = gameLocal.m_Grabber;
    idEntity *heldEntity = grabber->GetSelected();
    idEntity *equippedEntity = grabber->GetEquipped();

    // Dequip or drop the item in the grabber hands first
    if( equippedEntity != NULL )
    {
        grabber->Dequip();
    }
    else if(heldEntity != NULL)
    {
        grabber->Update( this, false );
    }
    else 
    {
        // Grabber is empty (no item is held), drop the current inventory item
        const CInventoryCursorPtr& cursor = InventoryCursor();

        CInventoryItemPtr item = cursor->GetCurrentItem();
        CInventoryCategoryPtr category = cursor->GetCurrentCategory();

        // Do we have a droppable item in the first place?
        if (item != NULL && item->IsDroppable() && item->GetCount() > 0)
        {
            // Retrieve the actual entity behind the inventory item
            idEntity* ent = item->GetItemEntity();
            DM_LOG(LC_INVENTORY, LT_INFO)LOGSTRING("Attempting to drop inventory entity %s\r", ent->name.c_str());

            // greebo: Try to locate a drop script function on the entity's scriptobject
            const function_t* dropScript = ent->scriptObject.GetFunction(TDM_INVENTORY_DROPSCRIPT);
            
            if( dropScript != NULL )
            {
                // Call the custom drop script
                DM_LOG(LC_INVENTORY, LT_DEBUG)LOGSTRING("Running inventory drop script...\r");
                idThread* thread = new idThread(dropScript);
                thread->CallFunctionArgs(dropScript, true, "ee", ent, this);
                thread->DelayedStart(0);
//////////////////////////////////////////////////// here ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////               
                // The dropScript changes the inventory count itself, so don't set 
                // bDropped to true here.
            }
            // greebo: Only place the entity in the world, if there is no custom dropscript
            // The flashbomb for example is spawning projectiles on its own.
            else if( DropToHands( ent, item ) )
            {

//////////////////////// acdc start - here is my custom fix, i think that this form is better for call a script when a item is dropped, i dont know about coding but this works for me/////////////////////

if ( ent->spawnArgs.GetBool( "drop_script" ) )
        {
            const function_t *func;
            idThread *thread;

            func = ent->scriptObject.GetFunction( ent->spawnArgs.GetString( "drop_script_call", "drop" ) );

            if ( func )
            {
                // create a thread and call the function
                thread = new idThread();
                thread->CallFunction( ent, func, true );
                thread->Start();
            }
        }

//////////////////////////////////////// end of acdc ////////////////////////////
                DM_LOG(LC_INVENTORY, LT_INFO)LOGSTRING("Item was successfully put in hands: %s\r", ent->name.c_str());
                bDropped = true;
            }
            else
            {
                // There wasn't space to drop the item
                StartSound( "snd_drop_item_failed", SND_CHANNEL_ITEM, 0, false, NULL );
                DM_LOG(LC_INVENTORY, LT_INFO)LOGSTRING("Grabber did not find space in the world to fit entity in hands: %s\r", ent->name.c_str());
            }

            // Decrease the inventory count (this will also clear empty categories)
            // This applies for both stackable as well as droppable items
            if( bDropped)
            {
                DM_LOG(LC_INVENTORY, LT_INFO)LOGSTRING("Item dropped, changing inventory count.\r");

                ChangeInventoryItemCount(item->GetName(), category->GetName(), -1); 
            }

            // Always update the HUD, the drop script might have changed the inventory count itself.
            inventoryHUDNeedsUpdate = true;
        }
    }
}

 

maybe the crashes are causes for this changes that i made, but with the 2.06 version without changes i get some crashes also, so i dont know, maybe this information can help to the darkmod team

- thanks for all

Acdc

Weapon.cpp Weapon.h

Link to comment
Share on other sites

in the two files that i was uploaded are my custom fix for the weapon problem, is another launchprojectile function that not replace the previous code, so actual weapons will be not changed, maybe needs a revision because i ' m not a expert coder, i am just beginning in this field. the changes are under the letters:

// acdc

Weapon.cpp Weapon.h

Link to comment
Share on other sites

I think the original intent was: if you are eager to customize item dropping, then you should take care of everything yourself.

I have managed to make spyglass droppable with custom method by adding the following code to class definition of playertools_spyglass:

    void inventoryDrop(entity ownerEntity);

and the following code at the file scope:
 

void playertools_spyglass::inventoryDrop(entity ownerEntity)
{
    ownerEntity.changeInvItemCount(getKey("inv_name"), getKey("inv_category"), -1);
}

It properly removes the spyglass from inventory. I have checked the C++ side, and it seems to do proper thing.

 

Probably you miss a parameter in your inventoryDrop method. Or maybe your item doesn't have the corresponding spawnargs.

Link to comment
Share on other sites

Quote

 

I think the original intent was: if you are eager to customize item dropping, then you should take care of everything yourself.

I have managed to make spyglass droppable with custom method by adding the following code to class definition of playertools_spyglass:

 

 

When was the spyglass not droppable?  I know I've thrown it several times in the past as a distraction tactic.

Link to comment
Share on other sites

9 minutes ago, Springheel said:

When was the spyglass not droppable?  I know I've thrown it several times in the past as a distraction tactic.

We are discussing the case when custom script method is called instead of builtin drop.

I have checked the script in SVN, and did not find inventoryDrop method anywhere. So I guess we have no custom-droppable items in the stock game.

Link to comment
Share on other sites

Speaking of the original issue with projectile spread.

Do we have any shooting weapons except for arrows? The base class atdm:projectile_arrow has spawnarg fire_along_playerview set. Theoretically, TDM once had weapons who fired directly from muzzle, instead of from view origin. Any idea if we have such weapons now (for purpose of testing) ?

Created issue 5041 about weapon spread.

UPDATE: Committed the fix to SVN. The spread works well with it, in my opinion.

Link to comment
Share on other sites

I don't think changing core mechanics like that is a good idea. It would be nice if you consulted the team first, plus this needs to be tested by at least several people.

It seems like the changes were tested but nothing was changed it the core mod, cool :)

Edited by peter_spy
Link to comment
Share on other sites

thanks for the help stgatilov, i can't compile the 2.07 version of the code for now because my visual studio 2013 only compiles 2.06 or below so i need made some changes in my pc programs. I will test the item dropping code tonight, maybe the script that i use for drop the item is not functional.

About the code of the projectile, if it cause problems for the game or players, can be added a function in weapon.cpp called "launchprojectile2" or "launchprojectileold"?, so the actual code for the arrow will be no affected for this and it will only works for custom weapon and testing. That is all, i will write the results later and maybe i will upload the pack of weapons in moddb, i think that more people wants make missions with a custom ambientation, (medieval, cyberpunk, post-apocalyptic, etc) and they can use my work

///////////////////// this is the change that i was made in the weapon.cpp based in the d3xp code //////////////////////////

// event defs

const idEventDef EV_Weapon_LaunchProjectilesEllipse("launchProjectilesEllipse", EventArgs('d', "num_projectiles", "", 'f', "spreada", "", 'f', "spreadb", "", 'f', "FuseOffset", "", 'f', "power", ""),
    EV_RETURNS_VOID, "no description");

// class defs

EVENT( EV_Weapon_LaunchProjectilesEllipse,    idWeapon::Event_LaunchProjectilesEllipse )


// code
void idWeapon::Event_LaunchProjectilesEllipse( int num_projectiles, float spreada, float spreadb, float fuseOffset, float power ) {
    idProjectile    *proj;
    idEntity        *ent;
    int                i;
    idVec3            dir;
    float            anga, angb;
    float            spin;
    float            distance;
    trace_t            tr;
    idVec3            start;
    idVec3            muzzle_pos;
    idBounds        ownerBounds, projBounds;

    if ( IsHidden() ) {
        return;
    }

//    if ( !projectileDict.GetNumKeyVals() ) {
//    const char *classname = weaponDef->dict.GetString( "classname" );
//    gameLocal.Warning( "No projectile defined on '%s'", classname );
//    return;
//    }
    CInventoryWeaponItemPtr weaponItem = owner->GetWeaponItem(weaponDef->dict.GetString("inv_weapon_name"));
    if (weaponItem == NULL) return;

    // Retrieve the currently active projectile def name from the inventory item
    const idStr& projectileDefName = weaponItem->GetProjectileDefName();

    if (projectileDefName.IsEmpty())
    {
        gameLocal.Warning("No projectile entityDef defined on '%s'", name.c_str());
        return;
    }

    const idDeclEntityDef* projectileDef = gameLocal.FindEntityDef(projectileDefName);

    if (projectileDef == NULL)
    {
        gameLocal.Warning("Projectile entityDef %s not found.", projectileDefName.c_str());
        return;
    }
    // avoid all ammo considerations on a client
    if ( !gameLocal.isClient ) {
        CInventoryWeaponItemPtr weaponItem = owner->GetCurrentWeaponItem();

        // check if we're out of ammo or the clip is empty
        int ammoAvail = weaponItem->HasAmmo();
        if (!ammoAvail || ((clipSize != 0) && (ammoClip <= 0))) {
            return;
        }
        weaponItem->UseAmmo(ammoRequired);

        if (clipSize && ammoRequired) {
            ammoClip -= powerAmmo ? (int)power : 1;
        }
    }

    // set the shader parm to the time of last projectile firing,
    // which the gun material shaders can reference for single shot barrel glows, etc
    renderEntity.shaderParms[ SHADERPARM_DIVERSITY ]    = gameLocal.random.CRandomFloat();
    renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ]    = -MS2SEC( gameLocal.time );

    if ( worldModel.GetEntity() ) {
        worldModel.GetEntity()->SetShaderParm( SHADERPARM_DIVERSITY, renderEntity.shaderParms[ SHADERPARM_DIVERSITY ] );
        worldModel.GetEntity()->SetShaderParm( SHADERPARM_TIMEOFFSET, renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] );
    }

    // calculate the muzzle position
    if ( barrelJointView != INVALID_JOINT && projectileDef->dict.GetBool( "launchFromBarrel" ) ) {
        // there is an explicit joint for the muzzle
        GetGlobalJointTransform( true, barrelJointView, muzzleOrigin, muzzleAxis );
    } else {
        // go straight out of the view
        muzzleOrigin = playerViewOrigin;
        muzzleAxis = playerViewAxis;
    }

    // add some to the kick time, incrementally moving repeat firing weapons back
    if ( kick_endtime < gameLocal.time ) {
        kick_endtime = gameLocal.time;
    }
    kick_endtime += muzzle_kick_time;
    if ( kick_endtime > gameLocal.time + muzzle_kick_maxtime ) {
        kick_endtime = gameLocal.time + muzzle_kick_maxtime;
    }

    if ( !gameLocal.isClient ) {
        ownerBounds = owner->GetPhysics()->GetAbsBounds();

        owner->AddProjectilesFired( num_projectiles );

        float spreadRadA = DEG2RAD( spreada );
        float spreadRadB = DEG2RAD( spreadb );

        for( i = 0; i < num_projectiles; i++ ) {
            //Ellipse Form
            spin = (float)DEG2RAD( 360.0f ) * gameLocal.random.RandomFloat();
            anga = idMath::Sin(spreadRadA * gameLocal.random.RandomFloat());
            angb = idMath::Sin(spreadRadB * gameLocal.random.RandomFloat());
            dir = playerViewAxis[ 0 ] + playerViewAxis[ 2 ] * ( angb*idMath::Sin( spin ) ) - playerViewAxis[ 1 ] * ( anga*idMath::Cos( spin ) );
            dir.Normalize();

            gameLocal.SpawnEntityDef( projectileDef->dict, &ent );
            if ( !ent || !ent->IsType( idProjectile::Type ) ) {
                const char *projectileName = weaponDef->dict.GetString( "def_projectile" );
                gameLocal.Error( "'%s' is not an idProjectile", projectileName );
            }

            proj = static_cast<idProjectile *>(ent);
            proj->Create( owner, muzzleOrigin, dir );

            projBounds = proj->GetPhysics()->GetBounds().Rotate( proj->GetPhysics()->GetAxis() );

            // make sure the projectile starts inside the bounding box of the owner
            if ( i == 0 ) {
                muzzle_pos = muzzleOrigin + playerViewAxis[ 0 ] * 2.0f;
                if ( ( ownerBounds - projBounds).RayIntersection( muzzle_pos, playerViewAxis[0], distance ) ) {
                    start = muzzle_pos + distance * playerViewAxis[0];
                }
                else {
                    start = ownerBounds.GetCenter();
                }
                gameLocal.clip.Translation( tr, start, muzzle_pos, proj->GetPhysics()->GetClipModel(), proj->GetPhysics()->GetClipModel()->GetAxis(), MASK_SHOT_RENDERMODEL, owner );
                muzzle_pos = tr.endpos;
            }

            proj->Launch( muzzle_pos, dir, pushVelocity, fuseOffset, power );
        }

        // toss the brass
        if( brassDelay >= 0 ) {
            PostEventMS( &EV_Weapon_EjectBrass, brassDelay );
        }
    }

    // add the light for the muzzleflash
    if ( !lightOn ) {
        MuzzleFlashLight();
    }

    owner->WeaponFireFeedback( &weaponDef->dict );

    // reset muzzle smoke
    weaponSmokeStartTime = gameLocal.time;

}

Thanks again for the support , i love the dark mod comunity, make my first mission is like a dream. I was doing mods for Quake4 and Doom3, but TheDarkMod haves more interesting things/functions (water, enemy vision based on light, attach a lot of things to the weapon, doors, enhanced Graphics , etc) and keep improving more and more.

-acdc

Link to comment
Share on other sites

  • 4 years later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recent Status Updates

    • Petike the Taffer

      I've finally managed to log in to The Dark Mod Wiki. I'm back in the saddle and before the holidays start in full, I'll be adding a few new FM articles and doing other updates. Written in Stone is already done.
      · 1 reply
    • nbohr1more

      TDM 15th Anniversary Contest is now active! Please declare your participation: https://forums.thedarkmod.com/index.php?/topic/22413-the-dark-mod-15th-anniversary-contest-entry-thread/
       
      · 0 replies
    • JackFarmer

      @TheUnbeholden
      You cannot receive PMs. Could you please be so kind and check your mailbox if it is full (or maybe you switched off the function)?
      · 1 reply
    • OrbWeaver

      I like the new frob highlight but it would nice if it was less "flickery" while moving over objects (especially barred metal doors).
      · 4 replies
    • nbohr1more

      Please vote in the 15th Anniversary Contest Theme Poll
       
      · 0 replies
×
×
  • Create New...