Code3Arena

PlanetQuake | Code3Arena | Tutorials | << Prev | Tutorial 26 | Next >>

menu

  • Home/News
  • ModSource
  • Compiling
  • Help!!!
  • Submission
  • Contributors
  • Staff
  • Downloads

    Tutorials
    < Index >
    1. Mod making 101
    2. Up 'n running
    3. Hello, QWorld!
    4. Infinite Haste
    5. Armor Piercing Rails
    6. Bouncing Rockets
    7. Cloaking
    8. Ladders
    9. Favourite Server
    10. Flame Thrower
    11. Vortex Grenades
    12. Grapple
    13. Lightning Discharge
    14. Locational Damage
    15. Leg Shots
    16. Weapon Switching
    17. Scoreboard frag-rate
    18. Vortex Grenades II
    19. Vulnerable Missiles
    20. Creating Classes
    21. Scrolling Credits
    22. Weapon Dropping
    23. Anti-Gravity Boots
    24. HUD scoreboard
    25. Flashlight and laser
    26. Weapon Positioning
    27. Weapon Reloading
    28. Progressive Zooming
    29. Rotating Doors
    30. Beheading (headshot!)
    31. Alt Weapon Fire
    32. Popup Menus I
    33. Popup Menus II
    34. Cluster Grenades
    35. Homing Rockets
    36. Spreadfire Powerup
    37. Instagib gameplay
    38. Accelerating rockets
    39. Server only Instagib
    40. Advanced Grapple Hook
    41. Unlagging your mod


    Articles
    < Index >
    1. Entities
    2. Vectors
    3. Good Coding
    4. Compilers I
    5. Compilers II
    6. UI Menu Primer I
    7. UI Menu Primer II
    8. UI Menu Primer III
    9. QVM Communication, Cvars, commands
    10. Metrowerks CodeWarrior
    11. 1.27g code, bugs, batch


    Links

  • Quake3 Files
  • Quake3 Forums
  • Q3A Editing Message Board
  • Quake3 Editing


    Feedback

  • SumFuka
  • Calrathan
  • HypoThermia
  • WarZone





    Site Design by:
    ICEmosis Design


  •  
    TUTORIAL 26 - Weapon Positioning
    by Carnage

    Ok since most of you people want to change the position of the weapon in the screen I have made here a small tutorial explaining how to do it. To introduce, this tutorial wil produce that you can change the weapon position on the screen in 3 diferent points:

    • Normal (Right-handed Q3A normal style)
    • Centered (Classic Quake and Doom style)
    • Left (For those of you that are left-handed)

    Ok this is all client side, in fact you send variables to the server and you get back the weapon where you want it. We are going to do changes to the following files. Only cgame will be modified:

    • cg_main.c
    • cg_weapons.c
    • cg_event.c
    • cg_local.h

    This tutorial has been updated to work with 1.27g source code, CG_MissileHitWall() now takes an extra argument IMPACTSOUND_DEFAULT.

     

    1. MAKING OUR DEFINITIONS

    Ok first of all we need to define our new command and variable

    A- Go to cg_local.h, line ~837 and insert below:

    extern vmCvar_t cg_deferPlayers;
    extern vmCvar_t gen_drawWeapon;
    

     

    B- Go to cg_main.c line ~117 and insert below:

    vmCvar_t cg_teamOverlayUserinfo;
    vmCvar_t gen_drawWeapon;
    

     

    C- Still in cg_main.c, line ~195, add:

    { &cg_stats, "cg_stats", "0", 0 },
    
    // the following variables are created in other parts of the system,
    // but we also reference them here
    
    { &gen_drawWeapon, "gen_drawWeapon", "2", CVAR_ARCHIVE },
    

     

    Ok, what we have just done is to make the game variable we will soon use. The client variable gen_drawWeapon is set as centered by default.

     

    2. ADDING THE CODE

    Ok now we are going to add the new function, so you can select the weapon position on screen:

    A1- At line ~970 of cg_weapons.c in function CG_AddViewWeapon() insert below:

    float fovOffset;
    vec3_t angles;
    weaponInfo_t *weapon;
    
    float gen_gunx, gen_guny, gen_gunz;
    

     

    A2- Now on line ~999 still in function CG_AddViewWeapon() insert below:

    if ( cg.testGun ) {
    	return;
    }
    
    gen_gunx = cg_gun_x.value; 
    gen_guny = cg_gun_y.value;
    gen_gunz = cg_gun_z.value;
    
    if ((gen_drawWeapon.integer > 1) && (gen_drawWeapon.integer < 4))
    {
    	switch (ps->weapon)
    	{
    		case WP_GAUNTLET:
    			gen_guny = cg_gun_y.value + 4*(gen_drawWeapon.integer-1);
    			break;
    		case WP_MACHINEGUN:
    			gen_guny = cg_gun_y.value + 3*(gen_drawWeapon.integer-1);
    			break;
    		case WP_SHOTGUN:
    			gen_guny = cg_gun_y.value + 3*(gen_drawWeapon.integer-1);
    			break;
    		case WP_GRENADE_LAUNCHER:
    			gen_guny = cg_gun_y.value + 5*(gen_drawWeapon.integer-1);
    			break;
    		case WP_ROCKET_LAUNCHER:
    			gen_guny = cg_gun_y.value + 5*(gen_drawWeapon.integer-1);
    			break;
    		case WP_LIGHTNING:
    			gen_guny = cg_gun_y.value + 3*(gen_drawWeapon.integer-1);
    			break;
    		case WP_RAILGUN:
    			gen_guny = cg_gun_y.value + 5*(gen_drawWeapon.integer-1);
    			break;
    		case WP_PLASMAGUN:
    			gen_guny = cg_gun_y.value + 4*(gen_drawWeapon.integer-1);
    			break;
    		case WP_BFG:
    			gen_guny = cg_gun_y.value + 5*(gen_drawWeapon.integer-1);
    			break;
    	}
    }
    

     

    A3- Now on line ~1019 still in function CG_AddViewWeapon() replace:

    VectorMA( hand.origin, cg_gun_x.value, cg.refdef.viewaxis[0], hand.origin );
    VectorMA( hand.origin, cg_gun_y.value, cg.refdef.viewaxis[1], hand.origin );
    VectorMA( hand.origin, (cg_gun_z.value+fovOffset), cg.refdef.viewaxis[2], hand.origin );
    

    with this:

    VectorMA( hand.origin, gen_gunx, cg.refdef.viewaxis[0], hand.origin );
    VectorMA( hand.origin, gen_guny, cg.refdef.viewaxis[1], hand.origin );
    VectorMA( hand.origin, (gen_gunz+fovOffset), cg.refdef.viewaxis[2], hand.origin );
    

     

    I'm going to explain what we have just done:

    On A1 we define 3 new float values (our new x, y, z position).

    On A2 we take the original x,y,z values and assigned them to our new values, then we search which weapon we are using, it "y" position is added to the value we type on the console minus 1 (so if we type gen_drawweapon 1 it will remain it's original value), the higher the value the more left it will be.

    On A3 we replace the the VectorMa() so it will take the new values we already modify.

     

    Ok now compile it, run it, go to the console and type: gen_drawweapon x (x takes values from 1 to 3).

    Hah, how nice, you start remembering the good old Doom days, you started firing the plasma gun, with the weapon positions on the center of the screen, you love it, next the good bfg10k, you can see now how the barrels look, yeah and finally you start firing the Railgun...

    Ahem.... what's wrong with the Railgun? It's central but the trail does not come from the railgun itself, what's the problem?

    Ok I will try to explain this, the railgun does not shoot, it makes a trace from the origin to where it hit and then it makes the trail, but the origin of the trail is not the weapon itself (like the other weapons are), but from a position on the screen.

    The most difficult thing about this code is in fact the railgun, but here is the damn fix.

     

    3. FIXING THE DAMN RAILGUN

    Now what we are going to do is to fix the railgun, by changing the trail origin position, we will start making a new rail trail origin.

    A- At line ~386 of cg_event.c in function CG_EntityEvent() and insert below:

    int clientNum;
    clientInfo_t *ci;
    vec3_t railtrail_origin;
    int pos;
    
    es = &cent->currentState;
    

     

    B- Now, still on cg_event.c in the same function go to line ~723 and replace:

    case EV_RAILTRAIL:
    	DEBUGNAME("EV_RAILTRAIL");
    	cent->currentState.weapon = WP_RAILGUN;
    
    	// if the end was on a nomark surface, don't make an explosion
    	if ( es->eventParm != 255 ) {
    		ByteToDir( es->eventParm, dir );
    		CG_MissileHitWall( es->weapon, es->clientNum,
    			position, dir, IMPACTSOUND_DEFAULT );
    	}
    
    	#if 1
    		CG_RailTrail( ci, es->origin2, es->pos.trBase );
    	#else
    		// the railtrail temp entity will be spawned when this player is added
    		VectorCopy( es->pos.trBase, cg_entities[clientNum].pe.railgunImpact );
    		cg_entities[clientNum].pe.railgunFlash = qtrue;
    	#endif
    
    	break;
    

    by this:

    case EV_RAILTRAIL:
    	DEBUGNAME("EV_RAILTRAIL");
    
    	cent->currentState.weapon = WP_RAILGUN;
    
    	// if the end was on a nomark surface, don't make an explosion
    	if ( es->eventParm != 255 ) {
    		ByteToDir( es->eventParm, dir );
    		CG_MissileHitWall( es->weapon, es->clientNum,
    			position, dir, IMPACTSOUND_DEFAULT );
    	}
    
    	if ( ((gen_drawWeapon.integer == 2) || (gen_drawWeapon.integer == 3))
    			 && es->clientNum == cg.snap->ps.clientNum
    			 && !cg.renderingThirdPerson)
    	{
    		if (gen_drawWeapon.integer == 2)
    			pos = -4;
    		else
    			pos = -8;
    
    		AngleVectors( cg.snap->ps.viewangles, NULL, railtrail_origin, NULL );
    		VectorMA( es->origin2, pos, railtrail_origin, railtrail_origin );
    
    		CG_RailTrail( ci, railtrail_origin, es->pos.trBase );
    	}
    	else
    	{
    		CG_RailTrail( ci, es->origin2, es->pos.trBase );
    	}
    
    	break;
    

     

    I will try to explain what this do, in A we define our railtrail_origin as a vector, like the old origin (origin2).

    On B we made a new railtrail event, the server check wich position you have the weapon, if you have it centered it change the railtrail origin -4 from his original position on "y", if you are lefthanded it change it -8.

    Then it adds the new position to the origin and the railtrail is spawned.

     

    4. WE ARE DONE!

    Now Compile it and you will see that every weapon work ok, enjoy it and have fun.

    Hope this tutorial help you in your mod. I use "gen_" variable name, because we are using it in our mod Generations Arena

    Special thanks to Codemonkey for helping me with the railtrail origin, and to Equim too.

    Any comment-> Carnage

    PlanetQuake | Code3Arena | Tutorials | << Prev | Tutorial 26 | Next >>