Home » SIRTECH CLASSICS » Jagged Alliance 2 » JA2 Technical Department » Fine-tuning stat progression in JA2
Fine-tuning stat progression in JA2[message #10970] Mon, 29 August 2005 18:46 Go to previous message
Snap is currently offline Snap

 
Messages:286
Registered:September 2000
Location: USA (by way of the Old Wo...
I had an idea to tweak stat progression a bit. The main idea here is that skills that affect the outcome of merc actions should be the same skills that are improved.

On the whole, I think the rate of stat progression is fine in the original. However, some stats, like wisdom or agility, hardly ever increase.

One thing to keep in mind is that physical stats (health, agi, dex, str, wis) increase at half the rate of skills (med, mech, expl, lead).

In the function StatChange that is called to update stats, the 3rd parameter (usNumChances) controls the quantity. A typical value is somewhere in the 5-25 range.

OK, so here are some suggestions:
  • More dex. and wis. for healing? I suspect that usNumChances here often truncates to zero, resulting in no award at all. Might even want to increase the rate for med. as well.

    HealCharacters Assignments.cpp(2385)
    StatChange(pDoctor, DEXTAMT,		(UINT16) (usUsedHealingPts / 100), FALSE);
    StatChange(pDoctor, WISDOMAMT,	(UINT16) (usUsedHealingPts / 100), FALSE);
    For the reference, usUsedHealingPts does not exceed med*(dex+wis)/2*(100+5*lev)/2400
  • No award for planting mines, you cheater! (Since it succedes 100% regardless of skill.)

    HandleSoldierDropBomb Handle Items.cpp(1379):
    // EXPLOSIVES GAIN (25):  Place a bomb, or buried and armed a mine
    // StatChange( pSoldier, EXPLODEAMT, 25, FALSE );
    NB: AFAIK, this does not affect cases where success is not guaranteed, such as when placing a bomb with a detonator.
  • Award a bit of wisdom for disarming mines and boobytraps? Not sure about this.

    BoobyTrapMessageBoxCallBack Handle Items.cpp(4410)
    BoobyTrapMessageBoxCallBack Handle Items.cpp(4463)
    BoobyTrapInMapScreenMessageBoxCallBack Handle Items.cpp(4510)
    BoobyTrapInMapScreenMessageBoxCallBack Handle Items.cpp(4556)
  • Wisdom for detecting mines (similar to detecting boobytraps):

    NearbyGroundSeemsWrong Handle Items.cpp(4702):
    StatChange( pSoldier, WISDOMAMT, (UINT16) (pObj->bTrap), FALSE );
  • Wisdom for making combos/special attachments (alongside with mech),

    AttachObject Items.cpp(3067):
    StatChange( pSoldier, WISDOMAMT, (INT8) ( 20 - AttachmentInfo[ bAttachInfoIndex ].bAttachmentSkillCheckMod )/5, FALSE );
    ...and for attaching detonators (alongside with expl).

    AttachObject Items.cpp(3158):
    StatChange( pSoldier, WISDOMAMT, 5, FALSE );
  • Wisdom for picking locks (it factors into the chance of success). More for electronic locks.

    AttemptToPickLock Keys.cpp(509)
    if (bReason == ELECTRONIC_LOCKPICKING_CHECK)
    	StatChange( pSoldier, WISDOMAMT, ( UINT16 ) ( pLock->ubPickDifficulty / 10 ), FALSE );
    else
    	StatChange( pSoldier, WISDOMAMT, ( UINT16 ) ( pLock->ubPickDifficulty / 15 ), FALSE );
  • Heh, I didn't know that you got expl. for blowing up enemies. Looks fine to me, just pointing this out.

    SoldierTakeDamage Soldier Control.cpp(6712)
  • Hand-to-hand attacks. Success of HtH attacks depends on the skills of the attacker and defender in the same way. The contribution of skills breaks down as follows (CalcChanceHTH in Tactical/Weapons.cpp):

    3*dex+agi+str+10*lev (knifing, punching)
    dex+agi+3*str+10*lev (stealing)

    First of all, should knifing be different from punching? Should parrying be different from attacking? How about this:

    3*dex+agi+str+10*lev (knifing attack)
    2*dex+3*agi+10*lev (knifing parry)
    2*dex+agi+2*str+10*lev (punching attack)
    2*dex+2*agi+str+10*lev (punching parry)

    Reason: Unarmed combat relies more on brute strength. Agility is more important for parrying because the attacker has the element of surprise.

    Awarded stats should reflect the breakdown of stats from above. For example, for a knife attack,

    UseBlade Weapons.cpp(1826)
    StatChange( pSoldier, DEXTAMT, usExpGain, ( UINT8 )( fGonnaHit ? FALSE : FROM_FAILURE ) );
    StatChange( pSoldier, AGILAMT, usExpGain/3, ( UINT8 )( fGonnaHit ? FALSE : FROM_FAILURE ) );
    StatChange( pSoldier, STRAMT, usExpGain/3, ( UINT8 )( fGonnaHit ? FALSE : FROM_FAILURE ) );
    Similarly, in other instances:

    UseBlade Weapons.cpp(1787)
    UseHandToHand Weapons.cpp(1933)
    UseHandToHand Weapons.cpp(1994)
    UseHandToHand Weapons.cpp(2032)
    UseHandToHand Weapons.cpp(2049)
    UseHandToHand Weapons.cpp(2058)
  • Throwing grenades. Let's make it more like knife throwing. This is getting really fancy Smile

    UseThrown Weapons.cpp(2138):
    // Snap: Find the number of real targets for grenade attack
    UINT16 usNumTargets = 0;
    if ( pTargetSoldier != NULL ) ++usNumTargets;
    else
    {
    	// search for an opponent near the target gridno
    	for ( bLoop = 0; bLoop < NUM_WORLD_DIRECTIONS; bLoop++ )
    	{
    		ubTargetID = WhoIsThere2( NewGridNo( pSoldier->sTargetGridNo, DirectionInc( bLoop ) ), pSoldier->bTargetLevel );
    		pTargetSoldier = NULL;
    		if ( ubTargetID != NOBODY )
    		{
    			pTargetSoldier = MercPtrs[ ubTargetID ];
    			if ( pTargetSoldier->bTeam != pSoldier->bTeam )
    			{
    				break;
    			}
    			else ++usNumTargets; // Snap
    		}
    	}
    }
    
    if ( pTargetSoldier )
    {
    	// ok this is a real attack on someone, grant experience
    
    	// Snap: calculate experience points for strength: weight x distance
    	UINT16 usHandItem = pSoldier->inv[HANDPOS].usItem;
    	// calculate actual range (in world units)
    	INT32 iRange = GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sTargetGridNo );
    	// 10 points for a regular grenade thrown at 100 units (1 cell = 10 units)
    	UINT16 usExpGain = ( Item[usHandItem].ubWeight * iRange + 30) / 60;
    	StatChange( pSoldier, STRAMT, usExpGain, FALSE );
    
    	// Snap: calculate experience points for dexterity and marksmanship
    	usExpGain = 5     // For at least one target
    		+ 2*(usNumTargets-1);   // For every additional target
    	BOOLEAN fGonnaHit = uiDiceRoll < uiHitChance;
    	if ( fGonnaHit ) usExpGain *= 2;   // For actually hitting the target :)
    	usExpGain += (UINT16) (100 - uiHitChance) / 10; // Extra exp for a difficult target
    	StatChange( pSoldier, DEXTAMT, usExpGain / 2, ( fGonnaHit ? FALSE : FROM_FAILURE ) );
    	StatChange( pSoldier, MARKAMT, usExpGain / 2, ( fGonnaHit ? FALSE : FROM_FAILURE ) );
    }
    Warning: this has not been tested!
  • When training skills (as opposed to physical stats) award some wisdom.

    TrainSoldierWithPts Assignments.cpp(4018)
    BOOLEAN fUseBrains = FALSE; // Snap
    // which stat to modify?
    switch( pSoldier -> bTrainStat )
    {
    	case( STRENGTH ):
    		ubChangeStat = STRAMT;
    		break;
    	case( DEXTERITY ):
    		ubChangeStat = DEXTAMT;
    		break;
    	case( AGILITY ):
    		ubChangeStat = AGILAMT;
    		break;
    	case( HEALTH ):
    		ubChangeStat = HEALTHAMT;
    		break;
    	case( LEADERSHIP ):
    		ubChangeStat = LDRAMT;
    		fUseBrains = TRUE;
    		break;
    	case( MARKSMANSHIP ):
    		ubChangeStat = MARKAMT;
    		fUseBrains = TRUE;
    		break;
    	case( EXPLOSIVE_ASSIGN ):
    		ubChangeStat = EXPLODEAMT;
    		fUseBrains = TRUE;
    		break;
    	case( MEDICAL ):
    		ubChangeStat = MEDICALAMT;
    		fUseBrains = TRUE;
    		break;
    	case( MECHANICAL ):
    		ubChangeStat = MECHANAMT;
    		fUseBrains = TRUE;
    		break;
    	// NOTE: Wisdom can't be trained!
    	default:
    		// BETA message
    		#ifdef JA2BETAVERSION
          ScreenMsg( FONT_ORANGE, MSG_BETAVERSION, L"TrainSoldierWithPts: ERROR - Unknown bTrainStat %d", pSoldier -> bTrainStat);
    		#endif
    return;
    }
    
    // give this merc a few chances to increase a stat (TRUE means it's training, reverse evolution doesn't apply)
    StatChange( pSoldier, ubChangeStat, sTrainPts, FROM_TRAINING );
    if (fUseBrains) StatChange( pSoldier, WISDOMAMT, sTrainPts/2, FROM_TRAINING ); // Snap
  • Reward teachers.

    HandleTrainingInSector Assignments.cpp(3526):
    // valid trainer is available, this gives the student a large training bonus!
    sTrainingPtsDueToInstructor = GetBonusTrainingPtsDueToInstructor( pTrainer, pStudent, pStudent -> bTrainStat, fAtGunRange, &usMaxPts );
    // Snap: Reward the trainer!
    StatChange( pTrainer, LDRAMT, sTrainingPtsDueToInstructor, FALSE );
    StatChange( pTrainer, WISDOMAMT, sTrainingPtsDueToInstructor, FALSE );
  • Award wisdom for training militia (alongside with leadership). This code is already present, but commented out for some reason. Can play with the rate here to get something reasonable - wisdom, of course, should not increase too fast.

    TrainTownInSector Assignments.cpp(4084):
    StatChange( pTrainer, WISDOMAMT, (UINT16) ( 1 + ( sTrainingPts / 400 ) ), FALSE );
  • Award health for exertion? Not sure about this.

    Edit: See a couple of posts below for more details.

    DeductPoints Points.cpp(513):
    // Adjust breath changes due to spending or regaining of energy
    sBPCost = AdjustBreathPts(pSoldier,sBPCost);
    // Snap: award some health for exertion
    // Do one StatChange roll per 100 breath points spent?
    // This might be expensive, because this function is called often!
    // NB: The scale of sBPCost is 100 per breath point
    if (PTR_OURTEAM && sBPCost > 0 && fProactive && PreRandom(10000) < sBPCost)
    {
    	StatChange( pSoldier, HEALTHAMT, 1, FALSE );
    }

Report message to a moderator

Master Sergeant
 
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Previous Topic: Is this a possibility?
Next Topic: Request: STI Imaging Format Tool
Goto Forum:
  


Current Time: Tue Feb 04 02:37:29 GMT+2 2025

Total time taken to generate the page: 0.02816 seconds